`; } function printER(id){ const er=ER_LIST.find(e=>e.id===id);if(!er)return; const html=_buildERDoc(er).replace('',``); const w=window.open('','_blank','width=800,height:1000'); w.document.write(html);w.document.close(); } function nextPVNo(){const nums=PV_LIST.map(p=>parseInt((p.pvNo||'').replace(/\D/g,''))||0);return'INZ-PV-'+String((Math.max(0,...nums)+1)).padStart(5,'0');} function nextCNNo(){const nums=CN_LIST.map(c=>parseInt((c.cnNo||'').replace(/\D/g,''))||0);return'INZ-CN-'+String((Math.max(0,...nums)+1)).padStart(5,'0');} const READONLY=new URLSearchParams(location.search).has('readonly'); let QUOT_LIST=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); // โ”€โ”€ Auto-seed quotations on first load โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function(){ const _seed=[{"id":"INZ-QUO-00329-R0","quotNo":"INZ-QUO-00329","revision":0,"client":"ZOCRAFT SDN BHD","clientPhone":"6011-1270 1070","date":"2026-06-27","remarks":"PJ1091 - Zo Craft, Austin Lake","handler":"Wei Ni","status":"In Progress","wonDeal":"2026-06-27","tag":"","finalAmt":135028.0,"totalAmt":135028.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-06-27T00:00:00.000Z","updatedAt":"2026-06-27T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00319-R0","quotNo":"INZ-QUO-00319","revision":0,"client":"Irene Chia Ai Ling","clientPhone":"6012 720 1655","date":"2026-06-01","remarks":"PJ1082 - Irene, Setia Tropika","handler":"Wei Ni","status":"In Progress","wonDeal":"2026-06-01","tag":"","finalAmt":21000.0,"totalAmt":21000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-06-03T00:00:00.000Z","updatedAt":"2026-06-03T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00275-R1","quotNo":"INZ-QUO-00275","revision":1,"client":"Channale","clientPhone":"6012 782 1885","date":"2026-05-23","remarks":"PJ1090 - Channale, Austin Crest","handler":"Wei Ni","status":"In Progress","wonDeal":"2026-05-23","tag":"","finalAmt":21000.0,"totalAmt":21000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-05-25T00:00:00.000Z","updatedAt":"2026-05-25T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00285-R1","quotNo":"INZ-QUO-00285","revision":1,"client":"Pei Jia","clientPhone":"6017 881 7365","date":"2026-05-24","remarks":"PJ1089 - Chong Pei Jia, Taman EkoFlora","handler":"Jacyln","status":"In Progress","wonDeal":"2026-05-24","tag":"","finalAmt":12000.0,"totalAmt":12000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-05-25T00:00:00.000Z","updatedAt":"2026-05-25T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00301-R0","quotNo":"INZ-QUO-00301","revision":0,"client":"Chua Che Yen","clientPhone":"6016 499 3339","date":"2026-05-20","remarks":"PJ1088 - Chua Che Yen, Taman Ekoflora","handler":"Jaclyn","status":"In Progress","wonDeal":"2026-05-20","tag":"","finalAmt":12000.0,"totalAmt":12000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-05-21T00:00:00.000Z","updatedAt":"2026-05-21T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00313-R3","quotNo":"INZ-QUO-00313","revision":3,"client":"Dews Lim","clientPhone":"6012-746 5180","date":"2026-04-30","remarks":"PJ1085 - Dews Lim, Eco Botanic","handler":"Jerry Chong","status":"In Progress","wonDeal":"2026-04-30","tag":"","finalAmt":252500.0,"totalAmt":252500.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-05-03T00:00:00.000Z","updatedAt":"2026-05-03T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00267-R1","quotNo":"INZ-QUO-00267","revision":1,"client":"Celine Lim","clientPhone":"6012 759 8838","date":"2026-04-15","remarks":"PJ1087 - Celine Lim, Sunway Lenang","handler":"Jerry Chong","status":"In Progress","wonDeal":"2026-04-15","tag":"","finalAmt":20000.0,"totalAmt":20000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-04-16T00:00:00.000Z","updatedAt":"2026-04-16T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00306-R3","quotNo":"INZ-QUO-00306","revision":3,"client":"Sherry","clientPhone":"6016 779 8637","date":"2026-04-13","remarks":"PJ1080 - Sherry, Taman Pelangi","handler":"Wei Ni","status":"In Progress","wonDeal":"2026-04-13","tag":"","finalAmt":855000.0,"totalAmt":855000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-04-13T00:00:00.000Z","updatedAt":"2026-04-13T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00260-R0","quotNo":"INZ-QUO-00260","revision":0,"client":"Chang Jia Wen","clientPhone":"6012 313 0871","date":"2026-01-16","remarks":"PJ1083 - Chang Jia Wen, PJ Old Town KL","handler":"Jerry Chong","status":"In Progress","wonDeal":"2026-01-16","tag":"","finalAmt":34626.0,"totalAmt":34626.0,"totalDisc":0,"taxAmt":0,"createdAt":"2026-01-16T00:00:00.000Z","updatedAt":"2026-01-16T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00293-R0","quotNo":"INZ-QUO-00293","revision":0,"client":"Mei Goh","clientPhone":"6016 754 4375","date":"2025-12-30","remarks":"PJ1081 - Mei Goh, Seri Alam","handler":"Jerry Chong","status":"In Progress","wonDeal":"2025-12-30","tag":"","finalAmt":16000.0,"totalAmt":16000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-12-31T00:00:00.000Z","updatedAt":"2025-12-31T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00287-R3","quotNo":"INZ-QUO-00287","revision":3,"client":"Lawrence Ong","clientPhone":"658912 1988","date":"2025-12-29","remarks":"PJ1078 - Lawrence Ong, Senadi Hill","handler":"Wei Ni","status":"In Progress","wonDeal":"2025-12-29","tag":"","finalAmt":255690.0,"totalAmt":255690.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-12-29T00:00:00.000Z","updatedAt":"2025-12-29T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00278-R1","quotNo":"INZ-QUO-00278","revision":1,"client":"Sherry","clientPhone":"6016 779 8637","date":"2025-12-11","remarks":"PJ1080 - Sherry, Taman Pelangi","handler":"Wei Ni","status":"In Progress","wonDeal":"2025-12-11","tag":"","finalAmt":15000.0,"totalAmt":15000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-12-13T00:00:00.000Z","updatedAt":"2025-12-13T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00279-R2","quotNo":"INZ-QUO-00279","revision":2,"client":"YJ","clientPhone":"6010 833 8382","date":"2025-12-09","remarks":"PJ1077 - YJ, Eco Botanic","handler":"Khang Cheng","status":"In Progress","wonDeal":"2025-12-09","tag":"","finalAmt":258000.0,"totalAmt":258000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-12-09T00:00:00.000Z","updatedAt":"2025-12-09T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00264-R3","quotNo":"INZ-QUO-00264","revision":3,"client":"Koh Tiong Sim","clientPhone":"658914 5347","date":"2025-11-05","remarks":"PJ1069 - Ms Chuang, Pulai","handler":"Khang Cheng","status":"In Progress","wonDeal":"2025-11-05","tag":"","finalAmt":687000.0,"totalAmt":687000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-11-05T00:00:00.000Z","updatedAt":"2025-11-05T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00245-R1","quotNo":"INZ-QUO-00245","revision":1,"client":"YJ","clientPhone":"6010 833 8382","date":"2025-09-18","remarks":"PJ1077 - YJ, Eco Botanic","handler":"Khang Cheng","status":"In Progress","wonDeal":"2025-09-18","tag":"","finalAmt":8550.0,"totalAmt":8550.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-09-18T00:00:00.000Z","updatedAt":"2025-09-18T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00204-R1","quotNo":"INZ-QUO-00204","revision":1,"client":"Jessy","clientPhone":"6019 728 6852","date":"2025-04-28","remarks":"PJ1063 - Jessy, Forte Ekoflora","handler":"Wei Ni","status":"In Progress","wonDeal":"2025-04-28","tag":"","finalAmt":1484000.0,"totalAmt":1484000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-04-29T00:00:00.000Z","updatedAt":"2025-04-29T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00214-R4","quotNo":"INZ-QUO-00214","revision":4,"client":"Allan","clientPhone":"6019-753 7370","date":"2025-04-25","remarks":"PJ1062 - Allan, Taman Gaya","handler":"Jerry Chong","status":"In Progress","wonDeal":"2025-04-25","tag":"","finalAmt":407000.0,"totalAmt":407000.0,"totalDisc":0,"taxAmt":0,"createdAt":"2025-04-26T00:00:00.000Z","updatedAt":"2025-04-26T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[],"pis":[]},{"id":"INZ-QUO-00190-R7","quotNo":"INZ-QUO-00190","revision":7,"client":"Jia Min","clientPhone":"6016-786 3738","date":"2026-06-08","remarks":"PJ1059 - Jia Min, Attleborough, Eco Botanic","handler":"Jing Wen","status":"In Progress","wonDeal":"2026-06-08","tag":"","finalAmt":341625,"totalAmt":341625,"totalDisc":0,"taxAmt":0,"createdAt":"2025-02-25T00:00:00.000Z","updatedAt":"2025-02-25T00:00:00.000Z","paymentTerm":"Design and Renovation (40%, 30%, 20%, 10%)","termCondition":"Terms & Conditions - Construction Use","designAgreement":"","sections":[{"title":"Masonry Work","items":[{"type":"subhdr","title":"Overall"},{"type":"item","no":1,"desc":"To Demolish Existing Floor Tiles and Wall Tiles c/w Patch Plaster Work at Entire Ground Floor","desc2":"Dimension : Floor Tiles - 849sqft Dimension : Wall Tiles (Door Area Only) - 204sqft","qty":1.0,"unit":"JOB","rate":5700.0,"cost":4166.0,"amount":5700.0,"foc":false,"focRate":0},{"type":"item","no":2,"desc":"To Demolish Existing Skirting to Receive New SPC Flooring Without Skirting c/w Patch Plaster Work at Ground Floor and First Floor","desc2":"","qty":1.0,"unit":"JOB","rate":2670.0,"cost":2000.0,"amount":2670.0,"foc":false,"focRate":0},{"type":"item","no":3,"desc":"To Demolish Existing Master Bathroom, Bedroom 1, Storeroom Door and Door Frame c/w Patch Plaster Work","desc2":"","qty":1.0,"unit":"JOB","rate":2730.0,"cost":2040.0,"amount":2730.0,"foc":false,"focRate":0},{"type":"item","no":4,"desc":"To Construct 4'' Concrete Base To Receive New Glass Handrail","desc2":"Dimension : L1650","qty":1.0,"unit":"JOB","rate":1200.0,"cost":950.0,"amount":1200.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Ground Floor"},{"type":"subhdr","title":"Car Porch"},{"type":"item","no":5,"desc":"To Construct New Concrete Stand and Lay New Pebble Stone Platform (*Not Including Pebble Stone)","desc2":"Dimension : W1200 L810 H30","qty":1.0,"unit":"JOB","rate":700.0,"cost":500.0,"amount":700.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Staircase"},{"type":"item","no":6,"desc":"To Supply Labour to Skim Staircase Riser and Demolish Riser at 18th Step c/w Patch Plaster Work","desc2":"","qty":1.0,"unit":"JOB","rate":1270.0,"cost":950.0,"amount":1270.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Kitchen"},{"type":"item","no":7,"desc":"To Core a Round Hole for Cooker Hood Ducting","desc2":"","qty":1.0,"unit":"JOB","rate":470.0,"cost":350.0,"amount":470.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Laundry"},{"type":"item","no":8,"desc":"To Construct New Brick Wall","desc2":"Dimension : W6476 H1500","qty":1.0,"unit":"JOB","rate":3200.0,"cost":2400.0,"amount":3200.0,"foc":false,"focRate":0},{"type":"item","no":9,"desc":"To Construct Concrete Base to Receive New Laundry Cabinet","desc2":"Dimension : W4350 D650 H75","qty":1.0,"unit":"JOB","rate":730.0,"cost":550.0,"amount":730.0,"foc":false,"focRate":0},{"type":"subhdr","title":"First Floor"},{"type":"subhdr","title":"Master Bathroom"},{"type":"item","no":10,"desc":"To Demolish Existing Wall Tiles, Floor Tiles and Sanitary Ware","desc2":"","qty":1.0,"unit":"JOB","rate":2400.0,"cost":1800.0,"amount":2400.0,"foc":false,"focRate":0},{"type":"item","no":11,"desc":"To Demolish Existing Wall and Construct New Shower Niche","desc2":"","qty":1.0,"unit":"JOB","rate":670.0,"cost":500.0,"amount":670.0,"foc":false,"focRate":0}]},{"title":"Plumbing Work","items":[{"type":"item","no":12,"desc":"To Supply and Install Inlet and Outlet Water Piping for Sink at Wet Kitchen","desc2":"","qty":1.0,"unit":"JOB","rate":820.0,"cost":700.0,"amount":820.0,"foc":false,"focRate":0},{"type":"item","no":13,"desc":"To Supply and Install Inlet and Outlet Water Piping for Robot Vacuum at Wet Kitchen","desc2":"","qty":1.0,"unit":"JOB","rate":820.0,"cost":700.0,"amount":820.0,"foc":false,"focRate":0},{"type":"item","no":14,"desc":"To Supply and Install Inlet Water Piping for Outdoor Faucet at Laundry","desc2":"","qty":1.0,"unit":"JOB","rate":350.0,"cost":300.0,"amount":350.0,"foc":false,"focRate":0},{"type":"item","no":15,"desc":"To Supply and Install Inlet and Outlet Water Piping for Washing Machine at Laundry","desc2":"","qty":1.0,"unit":"JOB","rate":820.0,"cost":700.0,"amount":820.0,"foc":false,"focRate":0},{"type":"item","no":16,"desc":"To Supply and Install Inlet and Outlet Water Piping for Sink at Laundry","desc2":"","qty":1.0,"unit":"JOB","rate":820.0,"cost":700.0,"amount":820.0,"foc":false,"focRate":0},{"type":"item","no":17,"desc":"To Supply And Install 75mm UPVC Outlet for Awning Existing Point at Laundry","desc2":"","qty":1.0,"unit":"JOB","rate":350.0,"cost":300.0,"amount":350.0,"foc":false,"focRate":0},{"type":"item","no":18,"desc":"To Supply Labour to Install 0.75hp Water Pump at Master Bathroom (Not Including Pump Machine)","desc2":"","qty":1.0,"unit":"JOB","rate":1100.0,"cost":900.0,"amount":1100.0,"foc":false,"focRate":0},{"type":"item","no":19,"desc":"To Supply Labour and Install Storage Water Heater at Master Bathroom","desc2":"","qty":1.0,"unit":"JOB","rate":940.0,"cost":800.0,"amount":940.0,"foc":false,"focRate":0},{"type":"item","no":20,"desc":"To Supply and Install New PPR Hot and Cold Water Piping for Shower Area, PPR Cold Piping for Other Areas at Master Bathroom","desc2":"","qty":1.0,"unit":"JOB","rate":2000.0,"cost":1700.0,"amount":2000.0,"foc":false,"focRate":0},{"type":"item","no":21,"desc":"To Relocate Inlet and Outlet Water Piping to Receive New Basin at Master Bathroom","desc2":"","qty":1.0,"unit":"JOB","rate":330.0,"cost":250.0,"amount":330.0,"foc":false,"focRate":0},{"type":"item","no":22,"desc":"To Install New Toilet Bowl at Master Bathroom","desc2":"","qty":1.0,"unit":"JOB","rate":330.0,"cost":250.0,"amount":330.0,"foc":false,"focRate":0},{"type":"item","no":23,"desc":"To Relocate Shower Area Floor Trap c/w Coring Work ,Sleeve Socket ,Sika Patch Back and Piping Connection at Master Bathroom","desc2":"","qty":1.0,"unit":"JOB","rate":820.0,"cost":700.0,"amount":820.0,"foc":false,"focRate":0},{"type":"item","no":24,"desc":"To Install New Toilet Bowl at Bathroom 2 and Bathroom 3","desc2":"","qty":2.0,"unit":"JOB","rate":330.0,"cost":250.0,"amount":660.0,"foc":false,"focRate":0},{"type":"item","no":25,"desc":"To Install New Basin at Bathroom 2 and Bathroom 3","desc2":"","qty":2.0,"unit":"JOB","rate":330.0,"cost":250.0,"amount":660.0,"foc":false,"focRate":0}]},{"title":"Tiles Work","items":[{"type":"subhdr","title":"Living, Kitchen, Laundry and Bedroom 1"},{"type":"item","no":26,"desc":"To Supply Labour to Lay New 800mmx800mm Floor Tiles and Build-In Skirting (*Not Including Floor Tiles)","desc2":"Overall Dimension : Floor Tiles - 828sqft","qty":828.0,"unit":"SQFT","rate":16.0,"cost":12.0,"amount":13248.0,"foc":false,"focRate":0},{"type":"item","no":27,"desc":"To Supply Labour to Lay New 2\"x4\" Mosaic Wall Tiles at Coffee Cabinet(*Not Including Floor Tiles)","desc2":"Dimension : W1200 H600","qty":1.0,"unit":"JOB","rate":600.0,"cost":450.0,"amount":600.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Master Bathroom"},{"type":"item","no":28,"desc":"To Supply Labour to Lay New 750mmx1500mm Wall Tiles and 750mmx1500mm Floor Tiles (*Not Including Wall Tiles and Floor Tiles)","desc2":"Dimension : Floor - W2500 L1520 Dimension : Wall - W2500 H3000x2, W1520 H3000x2 - c/w 3 Layers QuicSeal 104 Waterproofing - c/w 1500mmH for Shower Area Walls, 300mmH for Remaining Walls, Basin and Toilet Bowl Area - c/w Construct Shower Floor Drain","qty":1.0,"unit":"JOB","rate":11000.0,"cost":8200.0,"amount":11000.0,"foc":false,"focRate":0}]},{"title":"M&E Work","items":[{"type":"item","no":29,"desc":"Neutral Point","desc2":"","qty":17.0,"unit":"NOS","rate":65.0,"cost":50.0,"amount":1105.0,"foc":false,"focRate":0},{"type":"item","no":30,"desc":"Eyeball/Downlight/Surface Lighting Point","desc2":"","qty":103.0,"unit":"NOS","rate":100.0,"cost":73.0,"amount":10300.0,"foc":false,"focRate":0},{"type":"item","no":31,"desc":"LED Light Point","desc2":"","qty":45.0,"unit":"NOS","rate":60.0,"cost":45.0,"amount":2700.0,"foc":false,"focRate":0},{"type":"item","no":32,"desc":"Wall Light Point","desc2":"To Supply Labour to Prepare Wall Light Point","qty":4.0,"unit":"NOS","rate":150.0,"cost":110.0,"amount":600.0,"foc":false,"focRate":0},{"type":"item","no":33,"desc":"Cad 6 Data Point","desc2":"","qty":1.0,"unit":"NOS","rate":470.0,"cost":350.0,"amount":470.0,"foc":false,"focRate":0},{"type":"item","no":34,"desc":"13 Amp Power Socket Point","desc2":"","qty":57.0,"unit":"NOS","rate":170.0,"cost":130.0,"amount":9690.0,"foc":false,"focRate":0},{"type":"item","no":35,"desc":"13A with Heater Switch","desc2":"","qty":2.0,"unit":"NOS","rate":130.0,"cost":100.0,"amount":260.0,"foc":false,"focRate":0},{"type":"item","no":36,"desc":"2 Way Switch/2 Way Light Point","desc2":"","qty":1.0,"unit":"NOS","rate":210.0,"cost":160.0,"amount":210.0,"foc":false,"focRate":0},{"type":"item","no":37,"desc":"Fan Point","desc2":"","qty":6.0,"unit":"NOS","rate":110.0,"cost":80.0,"amount":660.0,"foc":false,"focRate":0},{"type":"item","no":38,"desc":"Hood Point","desc2":"","qty":1.0,"unit":"NOS","rate":230.0,"cost":170.0,"amount":230.0,"foc":false,"focRate":0},{"type":"item","no":39,"desc":"Hob Point","desc2":"","qty":1.0,"unit":"NOS","rate":230.0,"cost":170.0,"amount":230.0,"foc":false,"focRate":0},{"type":"item","no":40,"desc":"Oven Point","desc2":"","qty":1.0,"unit":"NOS","rate":350.0,"cost":260.0,"amount":350.0,"foc":false,"focRate":0},{"type":"item","no":41,"desc":"Exhaust Fan Point","desc2":"","qty":2.0,"unit":"NOS","rate":110.0,"cost":80.0,"amount":220.0,"foc":false,"focRate":0},{"type":"item","no":42,"desc":"Exhaust Fan Install","desc2":"","qty":2.0,"unit":"NOS","rate":40.0,"cost":30.0,"amount":80.0,"foc":false,"focRate":0},{"type":"item","no":43,"desc":"Light Install","desc2":"","qty":77.0,"unit":"NOS","rate":20.0,"cost":15.0,"amount":1540.0,"foc":false,"focRate":0},{"type":"item","no":44,"desc":"Wall Light Install","desc2":"","qty":4.0,"unit":"NOS","rate":30.0,"cost":20.0,"amount":120.0,"foc":false,"focRate":0},{"type":"item","no":45,"desc":"Led Casing Install","desc2":"","qty":6.0,"unit":"SET","rate":80.0,"cost":60.0,"amount":480.0,"foc":false,"focRate":0},{"type":"item","no":46,"desc":"Fan Install","desc2":"","qty":6.0,"unit":"NOS","rate":80.0,"cost":60.0,"amount":480.0,"foc":false,"focRate":0},{"type":"item","no":47,"desc":"Conceal Casing for TV Console","desc2":"","qty":1.0,"unit":"JOB","rate":1100.0,"cost":800.0,"amount":1100.0,"foc":false,"focRate":0},{"type":"item","no":48,"desc":"Change Switch Socket","desc2":"","qty":1.0,"unit":"JOB","rate":470.0,"cost":350.0,"amount":470.0,"foc":false,"focRate":0},{"type":"item","no":49,"desc":"TV Console Loose Cable","desc2":"","qty":1.0,"unit":"JOB","rate":370.0,"cost":280.0,"amount":370.0,"foc":false,"focRate":0},{"type":"item","no":50,"desc":"CCTV Camera Install","desc2":"","qty":3.0,"unit":"NOS","rate":55.0,"cost":40.0,"amount":165.0,"foc":false,"focRate":0},{"type":"item","no":51,"desc":"Move A/C Power Point","desc2":"","qty":1.0,"unit":"NOS","rate":150.0,"cost":110.0,"amount":150.0,"foc":false,"focRate":0}]},{"title":"Air Conditioning Piping Work","items":[{"type":"item","no":52,"desc":"To Supply and Modify Existing AC Copper Refrigerant Piping at Living Area","desc2":"- Copper Piping with Size 0.61mm - Insulation Foam with Thickness 1/2inch - Provision of all Necessary Fittings, Brackets and Supports - c/w Supply and Install Condensate Drain Pipe","qty":1.0,"unit":"JOB","rate":930.0,"cost":700.0,"amount":930.0,"foc":false,"focRate":0},{"type":"item","no":53,"desc":"To Supply Labour and Relocate Existing AC Copper Refrigerant Piping at Bedroom 1","desc2":"","qty":1.0,"unit":"JOB","rate":770.0,"cost":580.0,"amount":770.0,"foc":false,"focRate":0},{"type":"item","no":54,"desc":"To Supply Labour and Fitting to Install 1.0-1.5hp Wall-mounted AC at Bedroom1, Bedroom2 and Bedroom 3","desc2":"","qty":3.0,"unit":"JOB","rate":390.0,"cost":290.0,"amount":1170.0,"foc":false,"focRate":0},{"type":"item","no":55,"desc":"To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Master Bedroom","desc2":"","qty":1.0,"unit":"JOB","rate":520.0,"cost":390.0,"amount":520.0,"foc":false,"focRate":0},{"type":"item","no":56,"desc":"To Supply Labour and Fitting to Install Cassette AC at Living Area","desc2":"","qty":1.0,"unit":"JOB","rate":670.0,"cost":500.0,"amount":670.0,"foc":false,"focRate":0}]},{"title":"Plaster Ceiling & Partition Work","items":[{"type":"subhdr","title":"Ground Floor"},{"type":"item","no":57,"desc":"Plain Plaster Ceiling","desc2":"","qty":1164.0,"unit":"SQFT","rate":4.5,"cost":3.2,"amount":5238.0,"foc":false,"focRate":0},{"type":"item","no":58,"desc":"Dismantle Existing Plaster Ceiling","desc2":"","qty":380.0,"unit":"SQFT","rate":1.6,"cost":1.2,"amount":608.0,"foc":false,"focRate":0},{"type":"item","no":59,"desc":"L-Box at Living Staircase Area","desc2":"","qty":15.0,"unit":"FT","rate":16.0,"cost":12.0,"amount":240.0,"foc":false,"focRate":0},{"type":"item","no":60,"desc":"Manhole 12โ€œ","desc2":"","qty":2.0,"unit":"NOS","rate":100.0,"cost":75.0,"amount":200.0,"foc":false,"focRate":0},{"type":"item","no":61,"desc":"Manhole 18\" and A/C Hole","desc2":"","qty":1.0,"unit":"JOB","rate":200.0,"cost":150.0,"amount":200.0,"foc":false,"focRate":0},{"type":"item","no":62,"desc":"Light Holder at Living","desc2":"","qty":13.5,"unit":"FT","rate":20.0,"cost":15.0,"amount":270.0,"foc":false,"focRate":0},{"type":"item","no":63,"desc":"Light Holder at Bedroom 1","desc2":"","qty":12.5,"unit":"FT","rate":20.0,"cost":15.0,"amount":250.0,"foc":false,"focRate":0},{"type":"item","no":64,"desc":"Curtain Pelmet at Bedroom 1","desc2":"","qty":11.0,"unit":"FT","rate":20.0,"cost":15.0,"amount":220.0,"foc":false,"focRate":0},{"type":"item","no":65,"desc":"Cement Board Design at Dining","desc2":"","qty":1.0,"unit":"JOB","rate":1490.0,"cost":1118.0,"amount":1490.0,"foc":false,"focRate":0},{"type":"subhdr","title":"First Floor"},{"type":"item","no":66,"desc":"Plain Plaster Ceiling","desc2":"","qty":234.0,"unit":"SQFT","rate":4.5,"cost":3.2,"amount":1053.0,"foc":false,"focRate":0},{"type":"item","no":67,"desc":"Curve Partition Design c/w Light Holder at Master Bedroom","desc2":"","qty":1.0,"unit":"JOB","rate":1650.0,"cost":1235.6,"amount":1650.0,"foc":false,"focRate":0},{"type":"item","no":68,"desc":"Curtain Pelmet at Master Bedroom","desc2":"","qty":1.0,"unit":"JOB","rate":330.0,"cost":250.0,"amount":330.0,"foc":false,"focRate":0},{"type":"item","no":69,"desc":"Manhole 18โ€","desc2":"","qty":1.0,"unit":"NOS","rate":120.0,"cost":85.0,"amount":120.0,"foc":false,"focRate":0},{"type":"item","no":70,"desc":"Light Holder at Bathroom 1","desc2":"","qty":6.0,"unit":"FT","rate":20.0,"cost":15.0,"amount":120.0,"foc":false,"focRate":0},{"type":"item","no":71,"desc":"Modify Light Holder and L-Box at Family Hall Area","desc2":"","qty":1.0,"unit":"JOB","rate":1400.0,"cost":1045.0,"amount":1400.0,"foc":false,"focRate":0},{"type":"item","no":72,"desc":"Manhole 24\" at Bathroom 2","desc2":"","qty":1.0,"unit":"NOS","rate":130.0,"cost":95.0,"amount":130.0,"foc":false,"focRate":0},{"type":"item","no":73,"desc":"Cement Board Design at Master Bedroom","desc2":"","qty":1.0,"unit":"JOB","rate":3160.0,"cost":2368.0,"amount":3160.0,"foc":false,"focRate":0}]},{"title":"Aluminium and Glass Work","items":[{"type":"subhdr","title":"Overall"},{"type":"subhdr","title":"Staircase"},{"type":"item","no":74,"desc":"Sandblast Handrail c/w 12mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish","desc2":"Dimension: L1650 H1000 (Slanted)","qty":1.0,"unit":"SET","rate":2300.0,"cost":1700.0,"amount":2300.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Wet Kitchen"},{"type":"item","no":75,"desc":"Sliding Door c/w 5mm Tempered Clear Glass, 3mm PCB Solid Sheet and Top Track Aluminium 2.5\" Frame with Lattice Design","desc2":"Dimension: W1450 H2800","qty":1.0,"unit":"SET","rate":5000.0,"cost":3750.0,"amount":5000.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Laundry"},{"type":"item","no":76,"desc":"Aluminium Laundry Cabinet c/w 4G Door Frame and 4G Glass","desc2":"Remarks: Body using Exposed Coating Black method Dimension: W3000 D600 H900 Dimension: W1350 D600 H1500 - c/w Folding Cabinet Door Accessories - c/w Quartz Table Top - W3000 D600","qty":1.0,"unit":"SET","rate":15960.0,"cost":11970.0,"amount":15960.0,"foc":false,"focRate":0},{"type":"subhdr","title":"First Floor"},{"type":"subhdr","title":"Master Bathroom"},{"type":"item","no":77,"desc":"Mirror c/w 5mm Clear Glass and 3G Aluminium Frame in p/c Black Finish","desc2":"Dimension : Mirror - W800 H2300 - c/w Aluminium Shelving - W1600 D100","qty":1.0,"unit":"SET","rate":1900.0,"cost":1400.0,"amount":1900.0,"foc":false,"focRate":0},{"type":"item","no":78,"desc":"Shower Niches Aluminium Panel Shelving","desc2":"Dimension : W200 D100 Optional 2 : Quartz Stone - RM200/set","qty":3.0,"unit":"SET","rate":200.0,"cost":150.0,"amount":600.0,"foc":false,"focRate":0},{"type":"item","no":79,"desc":"Hanging Sliding Door with Europe Industry Style c/w Clear Glass Tinted Frosted Sticker and Aluminium Frame in p/c Black Finish","desc2":"Dimension: W1000 H2770 Upper Lattice Part : Clear Glass tinted Frosted Sticker Lower Lattice Part (H36\") : Solid Aluminium with p/c Black","qty":1.0,"unit":"SET","rate":3350.0,"cost":2500.0,"amount":3350.0,"foc":false,"focRate":0}]},{"title":"Flooring Work (SPC, Vinyl and Laminate)","items":[{"type":"item","no":80,"desc":"To Supply and Install 5mm SPC Click System Flooring including Necessary Beading and L Profile (without skirting) at First Floor","desc2":"","qty":1.0,"unit":"JOB","rate":6400.0,"cost":4800.0,"amount":6400.0,"foc":false,"focRate":0},{"type":"item","no":81,"desc":"To Supply and Install 5mm SPC Click System Flooring including L Profile (without skirting) at Staircase Area","desc2":"","qty":1.0,"unit":"JOB","rate":3900.0,"cost":2900.0,"amount":3900.0,"foc":false,"focRate":0}]},{"title":"Metal and Fabrication Work","items":[{"type":"item","no":82,"desc":"Round Design Metal Frame Shelving with Glass Shelves Design at Staircase","desc2":"","qty":1.0,"unit":"SET","rate":2000.0,"cost":1500.0,"amount":2000.0,"foc":false,"focRate":0},{"type":"item","no":83,"desc":"Metal Shelving c/w Led Lighting Design at Living","desc2":"Dimension : W1500 D200","qty":2.0,"unit":"SET","rate":400.0,"cost":300.0,"amount":800.0,"foc":false,"focRate":0},{"type":"item","no":84,"desc":"Metal Shelving c/w Led Lighting Design at Kitchen","desc2":"","qty":5.0,"unit":"SET","rate":330.0,"cost":250.0,"amount":1650.0,"foc":false,"focRate":0},{"type":"item","no":85,"desc":"Metal Shelving with Curve Design at Master Bedroom","desc2":"","qty":1.0,"unit":"SET","rate":670.0,"cost":500.0,"amount":670.0,"foc":false,"focRate":0},{"type":"item","no":86,"desc":"Metal Clothes Rail at Master Bedroom","desc2":"Dimension : W600 D300","qty":1.0,"unit":"SET","rate":330.0,"cost":250.0,"amount":330.0,"foc":false,"focRate":0}]},{"title":"Painting & Touch Up Work","items":[{"type":"item","no":87,"desc":"To Supply Labour and Material","desc2":"- To Clean Off Existing Exterior Wall Stain with Water Jet for Exterior Stain - To Touch Up Crack Line Area and Holes Area After Cleaning Work - To Lay Oil Sealer for Exterior Wall and Fencing - To Construct Painting Work for : a) Exterior Wall - SKK (2 color) b) Interior Wall - Jotun Majestic (True Beauty Series) (2color) c) Door, Door Frame - Included (1 Color) d) Ceiling - Jotun Majestic (True Beauty Series) (1 color)","qty":1.0,"unit":"JOB","rate":5600.0,"cost":4200.0,"amount":5600.0,"foc":false,"focRate":0},{"type":"item","no":88,"desc":"To Supply and Lay Vasari Lime Paint","desc2":"- Living and Kitchen Wall Area (306sqft) - Living and Kitchen Ceiling Area (515sqft) - Bedroom Wall Area (79sqft) - Upstairs Court Wall Area (235sqft) - Upstairs Court Ceiling Area (96sqft) - Master Bedroom Wall Area (492sqft) - Master Bedroom Ceiling Area (260sqft)","qty":1983.0,"unit":"SQFT","rate":8.0,"cost":6.0,"amount":15864.0,"foc":false,"focRate":0},{"type":"item","no":89,"desc":"To Supply and Lay Vasari Lime Paint","desc2":"- Staircase Wall Area (770sqft) - Staircase Ceiling Area (88sqft)","qty":858.0,"unit":"SQFT","rate":12.0,"cost":9.0,"amount":10296.0,"foc":false,"focRate":0},{"type":"item","no":90,"desc":"To Supply and Lay Mineral Sealer for Wall Only (Protective Layer)","desc2":"Dimension : 1882sqft","qty":1882.0,"unit":"SQFT","rate":2.7,"cost":2.0,"amount":5081.4,"foc":false,"focRate":0},{"type":"item","no":91,"desc":"To Supply Labour and Material to Lay Neighbour Dark Colour Paint","desc2":"","qty":1.0,"unit":"JOB","rate":400.0,"cost":300.0,"amount":0.0,"foc":false,"focRate":0}]},{"title":"Carpentry Work","items":[{"type":"subhdr","title":"Ground Floor"},{"type":"subhdr","title":"Car Porch"},{"type":"item","no":92,"desc":"Shoe Cabinet c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Shoe Cabinet - W1280 D450 H2700 - c/w Door Handle*6 Set","qty":1.0,"unit":"SET","rate":3760.0,"cost":2820.0,"amount":3760.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Living"},{"type":"item","no":93,"desc":"TV Cabinet c/w Solid Plywood and Cement Board in Vasari Paint and Selected Laminated Finish","desc2":"Dimension : TV Cabinet c/w Curve Design (Solid Plywood) - W5400 D380 H1600 Dimension : TV Cabinet Curve Design (Cement Board) - W5400 D380 H800+400","qty":1.0,"unit":"SET","rate":11600.0,"cost":8668.0,"amount":11600.0,"foc":false,"focRate":0},{"type":"item","no":94,"desc":"Coffee Cabinet c/w Solid Plywood In Vasari Paint and Selected Laminated Finish","desc2":"Dimension : Coffee Cabinet with Curve Design - W1200 D600 H2800 Dimension : 12mm Sintered Stone Table Top - W1200 D600 H2800","qty":1.0,"unit":"SET","rate":6850.0,"cost":5120.0,"amount":6850.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Dining"},{"type":"item","no":95,"desc":"Door with Feature Wall c/w Solid Plywood In Selected Laminated Finish","desc2":"Overall Dimension : W800 H2800 Overall Dimension : W800 H2800 Overall Dimension : W850 H2800","qty":3.0,"unit":"SET","rate":3350.0,"cost":2500.0,"amount":10050.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Wet Kitchen"},{"type":"item","no":96,"desc":"Top Cabinet, Base Cabinet and Tall Cabinet c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Tall Cabinet - W1505 D600 H2800 Dimension : Top Cabinet - W1970 D350 H1300 Dimension : Base Cabinet - W1970 D600 H900 Dimension : 12mm Sintered Stone Table Top (+Cooker Hood) - W1970 D600 Dimension : 12mm Sintered Stone Backsplash - W1970 H600","qty":1.0,"unit":"SET","rate":16600.0,"cost":12433.0,"amount":16600.0,"foc":false,"focRate":0},{"type":"item","no":97,"desc":"Top Cabinet and Base Cabinet c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Top Cabinet with Curve Design - W2930 D300 H1300 DImension : Base Cabinet - W3460 D600 H900 Dimension : 12mm Sintered Stone Table Top (+Sink Hole) - W3460 D600 Dimension : 12mm Sintered Stone Backsplash - W3460 H600 - Base Cabinet c/w Waterproofing Board","qty":1.0,"unit":"SET","rate":22000.0,"cost":16462.0,"amount":22000.0,"foc":false,"focRate":0},{"type":"subhdr","title":"First Floor"},{"type":"subhdr","title":"Master Bedroom"},{"type":"item","no":98,"desc":"Bedhead, King Size Divan and Bedside Drawer c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Bedhead with Curve Design - W2900+850 H1500 - c/w Bedhead Fluted with Spray Paint Dimension : Bedsize Drawer - W650 D450 H200, W720 D450 H200 Dimension : King Size Divan - Standard","qty":1.0,"unit":"SET","rate":9300.0,"cost":6970.0,"amount":9300.0,"foc":false,"focRate":0},{"type":"item","no":99,"desc":"Wardrobe c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Wardrobe with Curve Design - W1670 D600 H2770","qty":1.0,"unit":"SET","rate":8760.0,"cost":6570.0,"amount":8760.0,"foc":false,"focRate":0},{"type":"item","no":100,"desc":"Dressing Table with Drawer c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Dressing Table - W2350 D600 H150 Dimension : Drawer - W450 D600 H600","qty":1.0,"unit":"SET","rate":3800.0,"cost":2850.0,"amount":3800.0,"foc":false,"focRate":0},{"type":"item","no":101,"desc":"Wardrobe c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Wardrobe - W3250 D600 H2770 - c/w Glass Display Door - c/w 3mm Clear Mirror with 4 Sides Polished","qty":1.0,"unit":"SET","rate":18000.0,"cost":13505.0,"amount":18000.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Family Hall"},{"type":"item","no":102,"desc":"Display Cabinet c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Display Cabinet with Curve Design and Glass Display Door - W1860 D500 H1800","qty":1.0,"unit":"SET","rate":4350.0,"cost":3250.0,"amount":4350.0,"foc":false,"focRate":0},{"type":"item","no":103,"desc":"Hanging Cabinet c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Hanging Cabinet - W1100 D400 H900","qty":1.0,"unit":"SET","rate":2800.0,"cost":2100.0,"amount":2800.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Bedroom 1"},{"type":"item","no":104,"desc":"Bedhead and Dressing Table c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Bedhead - W3000+600 H1200 Dimension : Dressing Table - W1000 D450 H150","qty":1.0,"unit":"SET","rate":6050.0,"cost":4550.0,"amount":6050.0,"foc":false,"focRate":0},{"type":"item","no":105,"desc":"Wardrobe with Feature Wall c/w Solid Plywood In Selected Laminated Finish","desc2":"Dimension : Wardrobe - W1600 D600 H2800 - c/w 3mm Clear Mirror with 4 Sides Polished Dimension : Feature Wall with Shelving","qty":1.0,"unit":"SET","rate":10720.0,"cost":8040.0,"amount":10720.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Overall"},{"type":"item","no":106,"desc":"Led Light Strip","desc2":"","qty":1.0,"unit":"LS","rate":1200.0,"cost":900.0,"amount":1200.0,"foc":false,"focRate":0},{"type":"item","no":107,"desc":"Touch Up Work","desc2":"","qty":1.0,"unit":"LS","rate":4000.0,"cost":3000.0,"amount":4000.0,"foc":false,"focRate":0}]},{"title":"Miscellaneous Work","items":[{"type":"item","no":108,"desc":"To Supply 4 Waste Bins to Clear Debris During Renovation Period","desc2":"*Remarks : If the limit is exceeded, additional waste bins charges will be applied.","qty":1.0,"unit":"JOB","rate":1000.0,"cost":920.0,"amount":1000.0,"foc":false,"focRate":0},{"type":"item","no":109,"desc":"To Supply and Lay Floorgard Mat Floor Protection 1 Times During Renovation Period","desc2":"*Remarks : If the limit is exceeded, additional cleaning charges will be applied.","qty":1.0,"unit":"JOB","rate":2000.0,"cost":1800.0,"amount":2000.0,"foc":false,"focRate":0},{"type":"item","no":110,"desc":"To Supply Labour and Material to Clean The Entire Unit 2 Times (in the middle and the end of renovation period)","desc2":"*Remarks : If the limit is exceeded, additional cleaning charges will be applied.","qty":1.0,"unit":"JOB","rate":2000.0,"cost":1800.0,"amount":2000.0,"foc":false,"focRate":0}]},{"title":"Discount","items":[{"type":"item","no":111,"desc":"Special Discount","desc2":"","qty":1.0,"unit":"LS","rate":0,"cost":0,"amount":-8728.4,"foc":false,"focRate":0}]},{"title":"Omission","items":[{"type":"item","no":112,"desc":"Cad 6 Data Point","desc2":"","qty":1.0,"unit":"NOS","rate":0,"cost":0,"amount":-470.0,"foc":false,"focRate":0},{"type":"item","no":113,"desc":"3000k Strip Light","desc2":"","qty":1.0,"unit":"LS","rate":0,"cost":0,"amount":-23.5,"foc":false,"focRate":0},{"type":"item","no":114,"desc":"Aqara Smart Wall Switch","desc2":"","qty":1.0,"unit":"LS","rate":0,"cost":0,"amount":-481.5,"foc":false,"focRate":0},{"type":"item","no":115,"desc":"Hose Reel Set","desc2":"","qty":1.0,"unit":"LS","rate":0,"cost":0,"amount":-670.0,"foc":false,"focRate":0}]},{"title":"Variation Order","items":[{"type":"subhdr","title":"Masonry Work"},{"type":"item","no":116,"desc":"To Supply Labour and Material to Hacking Kitchen Wall Tiles c/w Plaster Finishing Skimcoat","desc2":"","qty":1.0,"unit":"JOB","rate":1800.0,"cost":0,"amount":1800.0,"foc":false,"focRate":0},{"type":"subhdr","title":"M&E Work"},{"type":"item","no":117,"desc":"Move Door Bell Point","desc2":"","qty":1.0,"unit":"NOS","rate":130.0,"cost":0,"amount":130.0,"foc":false,"focRate":0},{"type":"item","no":118,"desc":"Eubiq Track Install","desc2":"","qty":1.0,"unit":"NOS","rate":130.0,"cost":0,"amount":130.0,"foc":false,"focRate":0},{"type":"item","no":119,"desc":"Move Switch","desc2":"","qty":1.0,"unit":"NOS","rate":80.0,"cost":0,"amount":80.0,"foc":false,"focRate":0},{"type":"item","no":120,"desc":"Move Heater Point","desc2":"","qty":1.0,"unit":"NOS","rate":150.0,"cost":0,"amount":150.0,"foc":false,"focRate":0},{"type":"item","no":121,"desc":"Water Pump 13A Isolater","desc2":"","qty":1.0,"unit":"NOS","rate":200.0,"cost":0,"amount":200.0,"foc":false,"focRate":0},{"type":"item","no":122,"desc":"Move Data Point","desc2":"","qty":1.0,"unit":"NOS","rate":200.0,"cost":0,"amount":200.0,"foc":false,"focRate":0},{"type":"item","no":123,"desc":"Sensor Point","desc2":"","qty":1.0,"unit":"NOS","rate":350.0,"cost":0,"amount":350.0,"foc":false,"focRate":0},{"type":"item","no":124,"desc":"Dismantle and Reinstall Switch and Socket","desc2":"","qty":1.0,"unit":"JOB","rate":350.0,"cost":0,"amount":350.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Plaster Ceiling & Partition Work"},{"type":"item","no":125,"desc":"Add-on Wood Support at Kitchen c/w Fan Hook","desc2":"","qty":1.0,"unit":"JOB","rate":400.0,"cost":0,"amount":400.0,"foc":false,"focRate":0},{"type":"item","no":126,"desc":"Add-on Box-up at Car Porch","desc2":"","qty":1.0,"unit":"JOB","rate":130.0,"cost":0,"amount":130.0,"foc":false,"focRate":0},{"type":"item","no":127,"desc":"Modify Fan Hook at Master Bedroom, Bedroom 2 and Bedroom 3","desc2":"","qty":1.0,"unit":"JOB","rate":380.0,"cost":0,"amount":380.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Aluminium and Glass Work"},{"type":"item","no":128,"desc":"Shower Fixed Glass c/w 10mm Tempered Clear Glass","desc2":"","qty":1.0,"unit":"SET","rate":670.0,"cost":0,"amount":670.0,"foc":false,"focRate":0},{"type":"item","no":129,"desc":"Staircase Handrail Upgrade to Crystal Clear Glass","desc2":"","qty":1.0,"unit":"SET","rate":1250.0,"cost":0,"amount":1250.0,"foc":false,"focRate":0},{"type":"item","no":130,"desc":"Additional Soft-close accessories for Sliding Door at Master Bathroom","desc2":"FOC","qty":1.0,"unit":"SET","rate":0,"cost":0,"amount":0.0,"foc":true,"focRate":0},{"type":"subhdr","title":"Painting & Touch Up Work"},{"type":"item","no":131,"desc":"Change to Jotun Infinity Exterior Paint","desc2":"","qty":1.0,"unit":"JOB","rate":500.0,"cost":0,"amount":500.0,"foc":false,"focRate":0},{"type":"subhdr","title":"Carpentry Work"},{"type":"item","no":132,"desc":"Laminate 25pcs","desc2":"","qty":1.0,"unit":"LS","rate":3500.0,"cost":0,"amount":3500.0,"foc":false,"focRate":0},{"type":"item","no":133,"desc":"Modify Height for TV Cabinet, Coffee Cabinet and Wet Kitchen Cabinet","desc2":"","qty":1.0,"unit":"LS","rate":5000.0,"cost":0,"amount":5000.0,"foc":false,"focRate":0},{"type":"item","no":134,"desc":"Change TV Wall Laminate","desc2":"FOC","qty":1.0,"unit":"LS","rate":0,"cost":0,"amount":0.0,"foc":true,"focRate":0},{"type":"subhdr","title":"Supplies"},{"type":"item","no":135,"desc":"Pebble Stone Supplies","desc2":"","qty":1.0,"unit":"LS","rate":110.0,"cost":0,"amount":110.0,"foc":false,"focRate":0}]}],"pis":[]}]; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); const _ids=new Set(_ql.map(q=>q.id)); const _deleted=new Set(JSON.parse(localStorage.getItem('inzii_deleted_quots')||'[]')); let _added=0; _seed.forEach(q=>{ if(_ids.has(q.id)||_deleted.has(q.id))return; let _c=Date.now()+Math.random(); const uid=()=>'i'+(++_c).toString(36); (q.sections||[]).forEach(sec=>{if(!sec.id)sec.id=uid();(sec.items||[]).forEach(it=>{if(!it.id)it.id=uid();});}); _ql.push(q);_ids.add(q.id);_added++; }); if(_added>0){localStorage.setItem('inzii_quotations',JSON.stringify(_ql));console.log('[INZII] Seeded',_added,'quotations.');} })(); // โ”€โ”€ End auto-seed โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v2: set seeded quotations to status='Won' + inject INZ-QUO-00214-R4 sections โ”€โ”€ (function(){ let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); if(!_ql.length)return; let _c=Date.now();const uid=()=>'m'+(++_c).toString(36); let _chg=false; // Set all seeded projects to status='Won' const _wonIds=new Set(['INZ-QUO-00329-R0','INZ-QUO-00319-R0','INZ-QUO-00275-R1','INZ-QUO-00285-R1','INZ-QUO-00301-R0','INZ-QUO-00313-R3','INZ-QUO-00267-R1','INZ-QUO-00306-R3','INZ-QUO-00260-R0','INZ-QUO-00293-R0','INZ-QUO-00287-R3','INZ-QUO-00278-R1','INZ-QUO-00279-R2','INZ-QUO-00264-R3','INZ-QUO-00245-R1','INZ-QUO-00204-R1','INZ-QUO-00214-R4','INZ-QUO-00190-R7']); _ql.forEach(q=>{if(_wonIds.has(q.id)&&q.status!=='Won'){q.status='Won';_chg=true;}}); // Inject full sections for INZ-QUO-00214-R4 const _i=_ql.findIndex(q=>q.id==='INZ-QUO-00214-R4'); if(_i>=0&&(!_ql[_i].sections||!_ql[_i].sections.length)){ _ql[_i].sections=[ {title:'Masonry Work',items:[ {type:'subhdr',title:'Overall'},{type:'item',no:1,desc:'To Supply Labour to Demolish Existing Tiles Skirting and Skim Wall to Receive New SPC Flooring and Skirting at Staircase Area and First Floor',desc2:'',qty:1,unit:'JOB',rate:3350,cost:0,amount:3350,foc:false,focRate:0}, {type:'subhdr',title:'Ground Floor'},{type:'subhdr',title:'Car Porch'},{type:'item',no:2,desc:'To Extend Existing Column c/w Waterproofing',desc2:'Dimension: Same Height as Neighbour',qty:1,unit:'JOB',rate:2670,cost:0,amount:2670,foc:false,focRate:0}, {type:'subhdr',title:'Yard'},{type:'item',no:3,desc:'To Remove Existing Turfing and Construct New Concrete Floor and Raise Up Slab Level Same as Existing Walkway',desc2:'',qty:1,unit:'JOB',rate:6350,cost:0,amount:6350,foc:false,focRate:0}, {type:'subhdr',title:'Living'},{type:'item',no:4,desc:'To Dismantle Existing Window and Construct New Brick Wall c/w Patch Plaster Work',desc2:'Dimension : W595 H2700',qty:1,unit:'JOB',rate:870,cost:0,amount:870,foc:false,focRate:0}, {type:'subhdr',title:'Dining'},{type:'item',no:5,desc:'To Demolish Existing Brick Wall and Sliding Door',desc2:'Dimension : W3435 H3500',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:6,desc:'To Demolish Existing Brick Wall and Window c/w Patch Plaster Work',desc2:'Overall Dimension : W2415+3714+2600 H3500',qty:1,unit:'JOB',rate:2800,cost:0,amount:2800,foc:false,focRate:0},{type:'item',no:7,desc:'To Extend Dining Area c/w RC Slab and Necessary Column and Beams',desc2:'',qty:1,unit:'JOB',rate:52000,cost:0,amount:52000,foc:false,focRate:0},{type:'item',no:8,desc:'To Construct New Brick Wall c/w Patch Plaster Work',desc2:'Dimension : W3115 H3500',qty:1,unit:'JOB',rate:3550,cost:0,amount:3550,foc:false,focRate:0}, {type:'subhdr',title:'Wet Kitchen'},{type:'item',no:9,desc:'To Core a Round Hole for Cooker Hood Ducting',desc2:'',qty:1,unit:'JOB',rate:470,cost:0,amount:470,foc:false,focRate:0},{type:'item',no:10,desc:'To Demolish Existing Floor Tiles and Wall Tiles c/w Patch Plaster Work',desc2:'Dimension : Floor Tiles - 170sqft\nDimension : Wall Tiles - W3565+930 H3000',qty:1,unit:'JOB',rate:2550,cost:0,amount:2550,foc:false,focRate:0}, {type:'subhdr',title:'Dining and Wet Kitchen Extension Area'},{type:'item',no:11,desc:'To Construct New Brick Wall and Lintel to Receive New Door',desc2:'Dimension : W2830+W10285+2215 H3500',qty:1,unit:'JOB',rate:17500,cost:0,amount:17500,foc:false,focRate:0}, {type:'subhdr',title:'First Floor'},{type:'subhdr',title:"Son's Bedroom"},{type:'item',no:12,desc:'To Demolish Existing Brick Wall and Window c/w Patch Plaster Work',desc2:'Dimension : W3455 H3500',qty:1,unit:'JOB',rate:1950,cost:0,amount:1950,foc:false,focRate:0},{type:'item',no:13,desc:"To Extend Son's Bedroom c/w RC Slab and Necessary Column and Beams",desc2:'Dimension : 90sqft',qty:1,unit:'JOB',rate:18720,cost:0,amount:18720,foc:false,focRate:0}, {type:'subhdr',title:"Daughter's Bedroom"},{type:'item',no:14,desc:'To Demolish Existing Brick Wall and Window c/w Patch Plaster Work',desc2:'Dimension : W3630 H3500',qty:1,unit:'JOB',rate:1950,cost:0,amount:1950,foc:false,focRate:0},{type:'item',no:15,desc:"To Extend Daughter's Bedroom c/w RC Slab and Necessary Column, Beams and Waterproofing",desc2:'Dimension : 180sqft',qty:1,unit:'JOB',rate:37440,cost:0,amount:37440,foc:false,focRate:0}, {type:'subhdr',title:"Son's and Daughter's Bedroom Extension Area"},{type:'item',no:16,desc:'To Construct New Brick Wall and Lintel to Receive New Window c/w Patch Plaster Work',desc2:'Dimension : W10835+W2180+2180+2215',qty:1,unit:'JOB',rate:20400,cost:0,amount:20400,foc:false,focRate:0} ]}, {title:'Plumbing Work',items:[ {type:'item',no:17,desc:'To Supply and Install Inlet Water Piping for Water Pond',desc2:'',qty:1,unit:'JOB',rate:350,cost:0,amount:350,foc:false,focRate:0},{type:'item',no:18,desc:'To Relocate Inlet and Outlet Water Piping for Sink at Dry Kitchen Island',desc2:'',qty:1,unit:'JOB',rate:820,cost:0,amount:820,foc:false,focRate:0},{type:'item',no:19,desc:'To Supply and Install Inlet and Outlet Water Piping for Sink at Wet Kitchen and Dishwasher',desc2:'',qty:1,unit:'JOB',rate:1180,cost:0,amount:1180,foc:false,focRate:0},{type:'item',no:20,desc:'To Supply and Install Inlet and Outlet Water Piping for Water Tap at Backyard',desc2:'',qty:1,unit:'JOB',rate:350,cost:0,amount:350,foc:false,focRate:0},{type:'item',no:21,desc:'To Supply and Install Inlet and Outlet Water Piping for Washing Machine at Laundry',desc2:'',qty:1,unit:'JOB',rate:820,cost:0,amount:820,foc:false,focRate:0},{type:'item',no:22,desc:'To Relocate Inlet and Outlet Water Piping for Water Tap at Backyard',desc2:'',qty:1,unit:'JOB',rate:820,cost:0,amount:820,foc:false,focRate:0} ]}, {title:'Tiles Work',items:[ {type:'subhdr',title:'Wet Kitchen'},{type:'item',no:23,desc:'To Supply Labour to Lay New 600x600mm Floor Tiles (*Not Including Floor Tiles)',desc2:'Dimension : Floor Tiles - 170sqft',qty:170,unit:'SQFT',rate:11.5,cost:0,amount:1955,foc:false,focRate:0} ]}, {title:'M&E Work',items:[ {type:'item',no:24,desc:'Eyeball/Downlight/Surface Lighting Point',desc2:'',qty:125,unit:'NOS',rate:100,cost:0,amount:12500,foc:false,focRate:0},{type:'item',no:25,desc:'LED Light Point',desc2:'',qty:45,unit:'NOS',rate:60,cost:0,amount:2700,foc:false,focRate:0},{type:'item',no:26,desc:'Wall Light Point',desc2:'',qty:8,unit:'NOS',rate:150,cost:0,amount:1200,foc:false,focRate:0},{type:'item',no:27,desc:'Cad 6 Data Point',desc2:'',qty:1,unit:'NOS',rate:470,cost:0,amount:470,foc:false,focRate:0},{type:'item',no:28,desc:'Data, TV Point, Tel Point (Loose Cable)',desc2:'',qty:3,unit:'SET',rate:370,cost:0,amount:1110,foc:false,focRate:0},{type:'item',no:29,desc:'13 Amp Power Socket Point',desc2:'',qty:66,unit:'NOS',rate:170,cost:0,amount:11220,foc:false,focRate:0},{type:'item',no:30,desc:'20Amp Power Point (2.5mm)',desc2:'',qty:1,unit:'NOS',rate:350,cost:0,amount:350,foc:false,focRate:0},{type:'item',no:31,desc:'2 Way Switch/2 Way Light Point',desc2:'',qty:8,unit:'NOS',rate:210,cost:0,amount:1680,foc:false,focRate:0},{type:'item',no:32,desc:'Fan Point',desc2:'',qty:7,unit:'NOS',rate:110,cost:0,amount:770,foc:false,focRate:0},{type:'item',no:33,desc:'Hood Point',desc2:'',qty:1,unit:'NOS',rate:230,cost:0,amount:230,foc:false,focRate:0},{type:'item',no:34,desc:'Hob Point',desc2:'',qty:2,unit:'NOS',rate:230,cost:0,amount:460,foc:false,focRate:0},{type:'item',no:35,desc:'Oven Point',desc2:'',qty:1,unit:'NOS',rate:350,cost:0,amount:350,foc:false,focRate:0},{type:'item',no:36,desc:'Exhaust Fan Point',desc2:'',qty:5,unit:'NOS',rate:90,cost:0,amount:450,foc:false,focRate:0},{type:'item',no:37,desc:'Exhaust Fan Install',desc2:'',qty:5,unit:'NOS',rate:40,cost:0,amount:200,foc:false,focRate:0},{type:'item',no:38,desc:'Light Install',desc2:'',qty:120,unit:'NOS',rate:20,cost:0,amount:2400,foc:false,focRate:0},{type:'item',no:39,desc:'Led Casing Install',desc2:'',qty:8,unit:'SET',rate:80,cost:0,amount:640,foc:false,focRate:0},{type:'item',no:40,desc:'Pendant Light/ Hanging Light Install',desc2:'',qty:3,unit:'NOS',rate:55,cost:0,amount:165,foc:false,focRate:0},{type:'item',no:41,desc:'T5 Install',desc2:'',qty:1,unit:'SET',rate:80,cost:0,amount:80,foc:false,focRate:0},{type:'item',no:42,desc:'Fan Install',desc2:'',qty:7,unit:'NOS',rate:80,cost:0,amount:560,foc:false,focRate:0},{type:'item',no:43,desc:'Water Heater Install',desc2:'',qty:5,unit:'NOS',rate:170,cost:0,amount:850,foc:false,focRate:0},{type:'item',no:44,desc:'Conceal Casing for TV Console',desc2:'',qty:2,unit:'JOB',rate:370,cost:0,amount:740,foc:false,focRate:0},{type:'item',no:45,desc:'Change Switch Socket',desc2:'',qty:3,unit:'NOS',rate:20,cost:0,amount:60,foc:false,focRate:0},{type:'item',no:46,desc:'Conceal Amar Cable Point (1.5mm)',desc2:'',qty:9,unit:'NOS',rate:270,cost:0,amount:2430,foc:false,focRate:0},{type:'item',no:47,desc:'CCTV Install',desc2:'',qty:5,unit:'NOS',rate:55,cost:0,amount:275,foc:false,focRate:0},{type:'item',no:48,desc:'Relocate A/C Power Point',desc2:'',qty:5,unit:'NOS',rate:150,cost:0,amount:750,foc:false,focRate:0},{type:'item',no:49,desc:'20A Isolater Point (Amar Cable)',desc2:'',qty:1,unit:'NOS',rate:600,cost:0,amount:600,foc:false,focRate:0} ]}, {title:'Air Conditioning Piping Work',items:[ {type:'item',no:50,desc:'To Supply and Modify Existing AC Copper Refrigerant Piping at Dining',desc2:'- Copper Piping with Size 0.61mm\n- Insulation Foam with Thickness 1/2inch\n- Provision of all Necessary Fittings, Brackets and Supports',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:51,desc:'To Supply and Install New 2.0hp AC Copper Refrigerant Piping at Family Hall',desc2:'- Copper Piping with Size 0.61mm\n- Insulation Foam with Thickness 1/2inch\n- Provision of all Necessary Fittings, Brackets and Supports',qty:1,unit:'JOB',rate:470,cost:0,amount:470,foc:false,focRate:0},{type:'item',no:52,desc:"To Supply and Install New 1.5hp AC Copper Refrigerant Piping (20ft) at Son's Bedroom",desc2:'- Copper Piping with Size 0.61mm\n- Insulation Foam with Thickness 1/2inch\n- Provision of all Necessary Fittings, Brackets and Supports',qty:1,unit:'JOB',rate:680,cost:0,amount:680,foc:false,focRate:0},{type:'item',no:53,desc:"To Supply and Install New 2.0hp AC Copper Refrigerant Piping (28ft) at Daughter's Bedroom",desc2:'- Copper Piping with Size 0.61mm\n- Insulation Foam with Thickness 1/2inch\n- Provision of all Necessary Fittings, Brackets and Supports',qty:1,unit:'JOB',rate:1050,cost:0,amount:1050,foc:false,focRate:0},{type:'item',no:54,desc:'To Supply and Install New 2.5hp AC Copper Refrigerant Piping (20ft) at Master Bedroom',desc2:'- Copper Piping with Size 0.61mm\n- Insulation Foam with Thickness 1/2inch\n- Provision of all Necessary Fittings, Brackets and Supports',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:55,desc:'To Supply Labour to Conceal Water Pipe',desc2:'',qty:5,unit:'JOB',rate:175,cost:0,amount:875,foc:false,focRate:0},{type:'item',no:56,desc:'To Supply Labour and Fitting to Install 1.0-1.5hp Wall-mounted AC at Parents Room and Sons Bedroom',desc2:'',qty:2,unit:'JOB',rate:470,cost:0,amount:940,foc:false,focRate:0},{type:'item',no:57,desc:'To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Living and Family Hall',desc2:'',qty:2,unit:'JOB',rate:600,cost:0,amount:1200,foc:false,focRate:0},{type:'item',no:58,desc:'To Supply Labour and Fitting to Install Cassette AC at Dry Kitchen, Master Bedroom and Daughter Room',desc2:'',qty:3,unit:'JOB',rate:730,cost:0,amount:2190,foc:false,focRate:0} ]}, {title:'Plaster Ceiling & Partition Work',items:[ {type:'subhdr',title:'Ground Floor'},{type:'item',no:59,desc:'Plain Plaster Ceiling',desc2:'',qty:459,unit:'SQFT',rate:4.8,cost:0,amount:2203.2,foc:false,focRate:0},{type:'item',no:60,desc:'Plaster Ceiling Light Holder',desc2:'',qty:25,unit:'FT',rate:22,cost:0,amount:550,foc:false,focRate:0},{type:'item',no:61,desc:'Plaster Ceiling L Box',desc2:'',qty:35,unit:'FT',rate:21,cost:0,amount:735,foc:false,focRate:0},{type:'item',no:62,desc:'Fan Hook',desc2:'',qty:3,unit:'NOS',rate:65,cost:0,amount:195,foc:false,focRate:0},{type:'item',no:63,desc:'Manhole 450mm',desc2:'',qty:3,unit:'NOS',rate:120,cost:0,amount:360,foc:false,focRate:0}, {type:'subhdr',title:'First Floor'},{type:'item',no:64,desc:'Plain Plaster Ceiling',desc2:'',qty:1072,unit:'SQFT',rate:4.8,cost:0,amount:5145.6,foc:false,focRate:0},{type:'item',no:65,desc:'Plaster Ceiling Light Holder',desc2:'',qty:86,unit:'FT',rate:22,cost:0,amount:1892,foc:false,focRate:0},{type:'item',no:66,desc:'Plaster Ceiling L Box',desc2:'',qty:73,unit:'FT',rate:21,cost:0,amount:1533,foc:false,focRate:0},{type:'item',no:67,desc:'Fan Hook',desc2:'',qty:4,unit:'NOS',rate:65,cost:0,amount:260,foc:false,focRate:0},{type:'item',no:68,desc:'Manhole 400mm',desc2:'',qty:1,unit:'NOS',rate:120,cost:0,amount:120,foc:false,focRate:0},{type:'item',no:69,desc:'Manhole 600mm',desc2:'',qty:1,unit:'NOS',rate:150,cost:0,amount:150,foc:false,focRate:0},{type:'item',no:70,desc:'Master Bedroom Partition Add-on Rockwool',desc2:'',qty:1,unit:'SET',rate:1100,cost:0,amount:1100,foc:false,focRate:0},{type:'item',no:71,desc:'Partition Curve Design c/w Backlight Design at Family Hall',desc2:'',qty:1,unit:'SET',rate:2400,cost:0,amount:2400,foc:false,focRate:0} ]}, {title:'Aluminium and Glass Work',items:[ {type:'subhdr',title:'Ground Floor'},{type:'subhdr',title:'Dining and Dry Kitchen Area'},{type:'item',no:72,desc:'Sliding Door c/w 10mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish',desc2:'Dimension : W2680 H3165 (Max 3 Panels)\nRemarks: Using 5" High Performance Door Frame',qty:1,unit:'SET',rate:12600,cost:0,amount:12600,foc:false,focRate:0},{type:'item',no:73,desc:'Fixed Glass Panel c/w 12mm Tempered Clear Glass with Concealed MF "U" Channel',desc2:'Dimension : W2540 H3200 (Divide 2 Panels)',qty:1,unit:'SET',rate:6000,cost:0,amount:6000,foc:false,focRate:0},{type:'item',no:74,desc:'Fixed Glass Panel c/w 12mm Tempered Clear Glass with Concealed MF "U" Channel',desc2:'Dimension : W3450 H3200 (Divide 3 Panels)',qty:1,unit:'SET',rate:8010,cost:0,amount:8010,foc:false,focRate:0},{type:'item',no:75,desc:'Sliding Door with Fixed Glass Panel c/w 6mm Tempered Clear Glass and Standard 3.5" Top Track Aluminium Frame in p/c Black Finish',desc2:'Dimension : Sliding Door - W900 H2700\nDimension : Fixed Glass Panel - W1165 H2700',qty:1,unit:'SET',rate:5400,cost:0,amount:5400,foc:false,focRate:0}, {type:'subhdr',title:'Wet Kitchen'},{type:'item',no:76,desc:'Top Hung Window c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish',desc2:'Dimension : W2100 H600 (3 Panels)',qty:1,unit:'SET',rate:2350,cost:0,amount:2350,foc:false,focRate:0},{type:'item',no:77,desc:'High Performance Swing Door c/w 8.38mm Lami Clear Glass and Aluminium Frame in p/c Black Finish',desc2:'Dimension : W900 H2100',qty:1,unit:'SET',rate:2950,cost:0,amount:2950,foc:false,focRate:0}, {type:'subhdr',title:'Bathroom 4'},{type:'item',no:78,desc:'Shower Screen with Swing Door c/w 10mm Tempered Clear Glass and Accessories in Polished Finish',desc2:'Dimension : Swing Door - W750 H2100\nDimension : Fixed Glass Panel - W615 H2100 (Odd Shape)\nRemarks: Price quoted without top stabiliser',qty:1,unit:'SET',rate:2100,cost:0,amount:2100,foc:false,focRate:0}, {type:'subhdr',title:'First Floor'},{type:'subhdr',title:'Master Bathroom'},{type:'item',no:79,desc:'5mm Clear Glass Mirror with Backlight Design',desc2:'Dimension: W1165 H1000',qty:1,unit:'SET',rate:750,cost:0,amount:750,foc:false,focRate:0}, {type:'subhdr',title:'Bathroom 2'},{type:'item',no:80,desc:'Shower Screen with Pivot Door c/w 10mm Tempered Clear Glass and Accessories in Polished Finish',desc2:'Dimension : Pivot Door - W750 H2100\nDimension : Fixed Glass Panel - W450 H2100\n*Remarks: Price quoted without top stabiliser',qty:1,unit:'SET',rate:1800,cost:0,amount:1800,foc:false,focRate:0}, {type:'subhdr',title:"Daughter's Bedroom"},{type:'item',no:81,desc:'Fixed Panel c/w 12mm Tempered Clear Glass and U Channel',desc2:'Dimension: W3150 H3100',qty:1,unit:'SET',rate:7350,cost:0,amount:7350,foc:false,focRate:0}, {type:'subhdr',title:'Bathroom 3'},{type:'item',no:82,desc:'Shower Screen with Pivot Door c/w 10mm Tempered Clear Glass and Accessories in Polished Finish',desc2:'Dimension : Pivot Door - W750 H2100\nDimension : Fixed Glass Panel - W450 H2100\nRemarks: Price quoted without top stabiliser',qty:1,unit:'SET',rate:1800,cost:0,amount:1800,foc:false,focRate:0}, {type:'subhdr',title:'Overall'},{type:'item',no:83,desc:'To Dismantle Existing Casement & Fixed Windows and Reinstall Back',desc2:'Existing Size: W600mm H2800mm',qty:4,unit:'SET',rate:375,cost:0,amount:1500,foc:false,focRate:0} ]}, {title:'Decking Work',items:[ {type:'item',no:84,desc:'To Supply and Install WPC Deck Board onto 25mm H Aluminium Batten with Accessories & Mainhole',desc2:'Model: D14025H\nDimension : 140mm x 25mm x 3,050mm\nColor: Rosewood',qty:1,unit:'JOB',rate:16780,cost:0,amount:16780,foc:false,focRate:0} ]}, {title:'Awning and Metal Work',items:[ {type:'item',no:85,desc:'Deco Ceiling Awning with Rain Gutter',desc2:'Dimension: W4000 x L6500\n- U Purlin 2.0mm\n- Cliplock 0.47mm\n- Hollow 2"x4" 1.9mm, 2"x2" 1.6mm\n- Steel Gutter 0.7mm\n- Deco Ceiling Panel 0.47mm',qty:1,unit:'JOB',rate:24700,cost:0,amount:24700,foc:false,focRate:0} ]}, {title:'Painting & Touch Up Work',items:[ {type:'item',no:86,desc:'To Supply Labour and Material',desc2:"- To Clean Off Existing Exterior Wall Stain with Water Jet for Exterior Stain\n- To Touch Up Crack Line Area and Holes Area After Cleaning Work\n- To Lay Nippon 5170 Wall Sealer for Exterior Wall and Fencing\n- To Construct Painting Work for :\na) Exterior Wall - Nippon Weatherbond (3 Color)\nb) Interior Wall - Nippon Easywash (3 Color)\nc) Door, Door Frame - Included (1 Color)\nd) Ceiling - Included (1 Color)\ne) Staircase Railing - Included (1 Color)",qty:1,unit:'JOB',rate:22400,cost:0,amount:22400,foc:false,focRate:0}, {type:'item',no:87,desc:"To Supply and Lay Texture Paint in Son's Bedroom",desc2:'Dimension: W5035 H3000',qty:1,unit:'JOB',rate:3350,cost:0,amount:3350,foc:false,focRate:0} ]}, {title:'Wallpaper Supply',items:[ {type:'item',no:88,desc:'To Supply & Install 2 rolls of Wallpaper at Master Bedroom',desc2:'Dimension: W5890 H3000',qty:1,unit:'LS',rate:1600,cost:0,amount:1600,foc:false,focRate:0} ]}, {title:'Miscellaneous Work',items:[ {type:'item',no:89,desc:'To Supply 4 Waste Bins to Clear Debris During Renovation Period',desc2:'*Remarks : If the limit is exceeded, additional waste bins charges will be applied.',qty:1,unit:'JOB',rate:1000,cost:0,amount:1000,foc:false,focRate:0},{type:'item',no:90,desc:'To Supply and Lay Floorgard Mat Floor Protection 1 Times During Renovation Period',desc2:'*Remarks : If the limit is exceeded, additional cleaning charges will be applied.',qty:1,unit:'JOB',rate:2000,cost:0,amount:2000,foc:false,focRate:0},{type:'item',no:91,desc:'To Supply Labour and Material to Clean The Entire Unit 2 Times (in the middle and the end of renovation period)',desc2:'*Remarks : If the limit is exceeded, additional cleaning charges will be applied.',qty:1,unit:'JOB',rate:2000,cost:0,amount:2000,foc:false,focRate:0} ]}, {title:'Discount',items:[ {type:'item',no:92,desc:'Special Discount',desc2:'*This discounted price is limited to INZ-QUO-00214-R0. Any changes may result in an adjustment to the discount price.',qty:1,unit:'LS',rate:0,cost:0,amount:-9993.8,foc:false,focRate:0} ]}, {title:'Omission',items:[ {type:'subhdr',title:'Masonry Work'},{type:'item',no:93,desc:'To Dismantle Existing Window and Construct New Brick Wall c/w Patch Plaster Work',desc2:'Dimension : W595 H2700',qty:1,unit:'JOB',rate:0,cost:0,amount:-870,foc:false,focRate:0},{type:'item',no:94,desc:'To Demolish Existing Window and Construct New Brick Wall c/w Patch Plaster Work',desc2:'',qty:1,unit:'JOB',rate:0,cost:0,amount:-450,foc:false,focRate:0}, {type:'subhdr',title:'Tiles Work'},{type:'item',no:95,desc:'To Supply Labour to Lay New 600x600mm Floor Tiles (*Not Including Floor Tiles)',desc2:'Dimension : Floor Tiles - 170sqft',qty:170,unit:'SQFT',rate:0,cost:0,amount:-1955,foc:false,focRate:0}, {type:'subhdr',title:'M&E Work'},{type:'item',no:96,desc:'Eyeball/Downlight/Surface Lighting Point',desc2:'',qty:125,unit:'NOS',rate:0,cost:0,amount:-1875,foc:false,focRate:0},{type:'item',no:97,desc:'LED Light Point',desc2:'',qty:45,unit:'NOS',rate:0,cost:0,amount:-450,foc:false,focRate:0},{type:'item',no:98,desc:'Wall Light Point',desc2:'',qty:8,unit:'NOS',rate:0,cost:0,amount:-120,foc:false,focRate:0},{type:'item',no:99,desc:'Cad 6 Data Point',desc2:'',qty:1,unit:'NOS',rate:0,cost:0,amount:-20,foc:false,focRate:0},{type:'item',no:100,desc:'Data, TV Point, Tel Point (Loose Cable)',desc2:'',qty:3,unit:'SET',rate:0,cost:0,amount:-45,foc:false,focRate:0},{type:'item',no:101,desc:'13 Amp Power Socket Point',desc2:'',qty:66,unit:'NOS',rate:0,cost:0,amount:-2310,foc:false,focRate:0},{type:'item',no:102,desc:'2 Way Switch/2 Way Light Point',desc2:'',qty:8,unit:'NOS',rate:0,cost:0,amount:-200,foc:false,focRate:0},{type:'item',no:103,desc:'Fan Point',desc2:'',qty:7,unit:'NOS',rate:0,cost:0,amount:-70,foc:false,focRate:0},{type:'item',no:104,desc:'Hood Point',desc2:'',qty:1,unit:'NOS',rate:0,cost:0,amount:-15,foc:false,focRate:0},{type:'item',no:105,desc:'Hob Point',desc2:'',qty:2,unit:'NOS',rate:0,cost:0,amount:-30,foc:false,focRate:0},{type:'item',no:106,desc:'Oven Point',desc2:'',qty:1,unit:'NOS',rate:0,cost:0,amount:-20,foc:false,focRate:0},{type:'item',no:107,desc:'Exhaust Fan Point',desc2:'',qty:5,unit:'NOS',rate:0,cost:0,amount:-25,foc:false,focRate:0},{type:'item',no:108,desc:'Conceal Casing for TV Console',desc2:'',qty:2,unit:'JOB',rate:0,cost:0,amount:-30,foc:false,focRate:0},{type:'item',no:109,desc:'Conceal Amar Cable Point (1.5mm)',desc2:'',qty:9,unit:'NOS',rate:0,cost:0,amount:-135,foc:false,focRate:0},{type:'item',no:110,desc:'Relocate A/C Power Point',desc2:'',qty:5,unit:'NOS',rate:0,cost:0,amount:-50,foc:false,focRate:0},{type:'item',no:111,desc:'20A Isolater Point (Amar Cable)',desc2:'',qty:1,unit:'NOS',rate:0,cost:0,amount:-50,foc:false,focRate:0}, {type:'subhdr',title:'Air Conditioning Piping Work'},{type:'item',no:112,desc:'To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Living',desc2:'',qty:1,unit:'JOB',rate:0,cost:0,amount:-600,foc:false,focRate:0},{type:'item',no:113,desc:'To Supply Labour and Fitting to Install 1.0-1.5hp Wall-mounted AC at Parents Room and Sons Bedroom',desc2:'',qty:2,unit:'JOB',rate:0,cost:0,amount:-940,foc:false,focRate:0},{type:'item',no:114,desc:'To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Living and Family Hall',desc2:'',qty:2,unit:'JOB',rate:0,cost:0,amount:-1200,foc:false,focRate:0},{type:'item',no:115,desc:'To Supply Labour and Fitting to Install Cassette AC at Dry Kitchen, Master Bedroom and Daughter Room',desc2:'',qty:3,unit:'JOB',rate:0,cost:0,amount:-2190,foc:false,focRate:0}, {type:'subhdr',title:'Aluminium and Glass Work'},{type:'item',no:116,desc:'5mm Clear Glass Mirror with Backlight Design at Master Bathroom',desc2:'',qty:1,unit:'SET',rate:0,cost:0,amount:-750,foc:false,focRate:0},{type:'item',no:117,desc:'To Dismantle Existing Casement & Fixed Windows and Reinstall Back',desc2:'',qty:1,unit:'JOB',rate:0,cost:0,amount:-375,foc:false,focRate:0}, {type:'subhdr',title:'Decking Work'},{type:'item',no:118,desc:'To Supply and Install WPC Deck Board onto 25mm H Aluminium Batten with Accessories & Mainhole',desc2:'',qty:1,unit:'JOB',rate:0,cost:0,amount:-16780,foc:false,focRate:0}, {type:'subhdr',title:'Wallpaper Supply'},{type:'item',no:119,desc:'To Supply & Install 2 rolls of Wallpaper at Master Bedroom',desc2:'Dimension: W5890 H3000',qty:1,unit:'LS',rate:0,cost:0,amount:-1600,foc:false,focRate:0} ]}, {title:'Variation Order',items:[ {type:'subhdr',title:'Masonry Work'},{type:'item',no:120,desc:'To Construct Brick Wall to Seal up Window at Living',desc2:'',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:121,desc:'To Construct Staircase Cerb for Glass Handrail at Staircase Area',desc2:'',qty:1,unit:'JOB',rate:2400,cost:0,amount:2400,foc:false,focRate:0},{type:'item',no:122,desc:'To Demolish Existing Floor Tiles at Laundry',desc2:'',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:123,desc:'To Demolish Existing SPC Floor at First Floor',desc2:'',qty:1,unit:'JOB',rate:1100,cost:0,amount:1100,foc:false,focRate:0},{type:'item',no:124,desc:'To Demolish Existing Floor for 2 not Feng Shui Hole',desc2:'',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:125,desc:'To Construct New Brick Wall to Seal up Window at Living Hall',desc2:'',qty:1,unit:'JOB',rate:800,cost:0,amount:800,foc:false,focRate:0},{type:'item',no:126,desc:'To Construct New Brick Wall to Seal up Window at First Floor Bathroom',desc2:'',qty:1,unit:'JOB',rate:600,cost:0,amount:600,foc:false,focRate:0}, {type:'subhdr',title:'M&E Work'},{type:'item',no:127,desc:'Aircond Point at Dry Kitchen and Master Bedroom',desc2:'',qty:2,unit:'NOS',rate:350,cost:0,amount:700,foc:false,focRate:0},{type:'item',no:128,desc:'Wall Box 3 Phase Point (6mm Cable)',desc2:'',qty:1,unit:'NOS',rate:2500,cost:0,amount:2500,foc:false,focRate:0},{type:'item',no:129,desc:'Fan Point',desc2:'',qty:2,unit:'NOS',rate:100,cost:0,amount:200,foc:false,focRate:0},{type:'item',no:130,desc:'Fan Install',desc2:'',qty:2,unit:'NOS',rate:80,cost:0,amount:160,foc:false,focRate:0},{type:'item',no:131,desc:'2 Way Switch/2 Way Light Point',desc2:'',qty:5,unit:'NOS',rate:185,cost:0,amount:925,foc:false,focRate:0}, {type:'subhdr',title:'Air Conditioning Piping Work'},{type:'item',no:132,desc:'To Supply and Modify Existing AC Copper Refrigerant Piping at Living',desc2:'',qty:1,unit:'JOB',rate:950,cost:0,amount:950,foc:false,focRate:0},{type:'item',no:133,desc:"To Supply and Modify Existing AC Copper Refrigerant Piping at Parent's Room",desc2:'',qty:1,unit:'JOB',rate:550,cost:0,amount:550,foc:false,focRate:0},{type:'item',no:134,desc:'To Supply and Modify Existing AC Copper Refrigerant Piping at Walk-in Closet',desc2:'',qty:1,unit:'JOB',rate:750,cost:0,amount:750,foc:false,focRate:0},{type:'item',no:135,desc:"To Supply Labour to Conceal Water Pipe at Living, Walk-in Closet and Parent's Room",desc2:'',qty:3,unit:'JOB',rate:175,cost:0,amount:525,foc:false,focRate:0},{type:'item',no:136,desc:'To Supply Labour and Fitting to Install Cassette AC at Living and Walk-in Closet',desc2:'',qty:2,unit:'JOB',rate:730,cost:0,amount:1460,foc:false,focRate:0}, {type:'subhdr',title:'Plaster Ceiling & Partition Work'},{type:'item',no:137,desc:'Plain Plaster Ceiling at Ground Floor',desc2:'',qty:140,unit:'SQFT',rate:4.8,cost:0,amount:672,foc:false,focRate:0},{type:'item',no:138,desc:'Magnetic Track Light c/w Metal Support',desc2:'',qty:1,unit:'JOB',rate:1100,cost:0,amount:1100,foc:false,focRate:0},{type:'item',no:139,desc:'Box-up Partition at Laundry',desc2:'',qty:1,unit:'JOB',rate:450,cost:0,amount:450,foc:false,focRate:0},{type:'item',no:140,desc:'Ceramic Light at Foyer, Living and Dry Kitchen',desc2:'',qty:11,unit:'NOS',rate:150,cost:0,amount:1650,foc:false,focRate:0},{type:'item',no:141,desc:'Plain Plaster Ceiling at First Floor',desc2:'',qty:57,unit:'SQFT',rate:4.8,cost:0,amount:273.6,foc:false,focRate:0},{type:'item',no:142,desc:'Install U Profile at Master Bathroom',desc2:'',qty:1,unit:'JOB',rate:400,cost:0,amount:400,foc:false,focRate:0},{type:'item',no:143,desc:'To Modify Plaster Ceiling at Master Bedroom',desc2:'',qty:1,unit:'JOB',rate:660,cost:0,amount:660,foc:false,focRate:0}, {type:'subhdr',title:'Aluminium and Glass Work'},{type:'item',no:144,desc:'12mm Tempered Clear Glass c/w Bottom Concealed MF "U" Channel at Staircase',desc2:'',qty:1,unit:'SET',rate:8800,cost:0,amount:8800,foc:false,focRate:0},{type:'item',no:145,desc:'Semi Louver Semi Glass Swing Door Inner & Outer (TNB Meter)',desc2:'*c/w Dismantle + Coating + Install Back Existing Unit',qty:1,unit:'SET',rate:520,cost:0,amount:520,foc:false,focRate:0},{type:'item',no:146,desc:'Full Louver Swing Door Inner & Outer (Garbage Area)',desc2:'*c/w Dismantle + Coating + Install Back Existing Unit',qty:1,unit:'SET',rate:800,cost:0,amount:800,foc:false,focRate:0}, {type:'subhdr',title:'Flooring Work'},{type:'item',no:147,desc:'To Supply Labour and Material for Self Leveling at Staircase and Entire First Floor Flooring',desc2:'',qty:1,unit:'JOB',rate:6700,cost:0,amount:6700,foc:false,focRate:0},{type:'item',no:148,desc:'To Supply Labour to Lay 6mm SPC Flooring at Staircase Area and First Floor',desc2:'',qty:1,unit:'JOB',rate:19400,cost:0,amount:19400,foc:false,focRate:0}, {type:'subhdr',title:'Decking Work'},{type:'item',no:149,desc:'To Supply and Install Solid WPC Deck 140x22xRL with Aluminium 38x38 Batten',desc2:'',qty:1,unit:'JOB',rate:17960,cost:0,amount:17960,foc:false,focRate:0}, {type:'subhdr',title:'Discount'},{type:'item',no:150,desc:'Special Discount',desc2:'',qty:1,unit:'LS',rate:0,cost:0,amount:-250.6,foc:false,focRate:0} ]} ]; _ql[_i].sections.forEach(sec=>{sec.id=uid();sec.items.forEach(it=>{it.id=uid();});}); _chg=true; } if(_chg){ localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); QUOT_LIST.length=0;QUOT_LIST.push(..._ql); console.log('[INZII] Migration v2 applied.'); } })(); // โ”€โ”€ End migration v2 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v3: import payments (268) + invoices (95) โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v3'))return; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); let _c=Date.now();const uid=()=>'m'+(++_c).toString(36); let chg=false; const findQ=baseNo=>_ql.find(q=>q.id.replace(/-R\d+$/,'')===baseNo||q.id===baseNo); // โ”€โ”€ Stub quotations for historical projects โ”€โ”€ const stubs=[ ['INZ-QUO-00001','Leroy','PJ1025 - Leroy, Wave Marina Bay','609873 4954'],['INZ-QUO-00002','Y','PJ1026 - Ah Y, The Crest Austin','6017-712 7979'],['INZ-QUO-00003','Ong Yi Hao','PJ1027 - Ong Yi Hao, Luxura Selangor','6017-303 2614'],['INZ-QUO-00004','Mr Tiong and Miss Elaine','PJ1003 - Elaine, Kota Kemuning Selangor','6012-799 8987'],['INZ-QUO-00007','Leroy','PJ1025 - Leroy, Wave Marina Cove','609873 4954'],['INZ-QUO-00008','Kelvin','PJ1029 - Kelvin, Cello Tebrau','6010-824 6810'],['INZ-QUO-00009','Xenos Fam','PJ1030 - Xenos Fam, St Marco Park Kulai','609050 8646'],['INZ-QUO-00010','Koon Tar','DP0069 - Koon Tar, Horizon Hills','6011-3670 2141'],['INZ-QUO-00013','Alys Lim','PJ1032 - Alys Lim, Horizon Hills','6011-1177 7154'],['INZ-QUO-00014','Koon Tar','PJ1031 - Koon Tar, Horizon Hills','6011-3670 2141'],['INZ-QUO-00015','Simon','PJ1033 - Simon, Greystone Adda Height','608711 9038'],['INZ-QUO-00016','Lee Hing','PJ1035 - Monaco Dining','6016-663 7004'],['INZ-QUO-00017','Lee Hing','PJ1035 - Monaco Signature','6016-663 7004'],['INZ-QUO-00026','Elva','PJ1036 - Elva, Bandar Seri Alam','6011-2176 4124'],['INZ-QUO-00027','Kelvin','PJ1029 - Kelvin, Cello Tebrau','6010-824 6810'],['INZ-QUO-00030','Jackson','PJ1037 - Jackson, Senibong Cove','609138 9156'],['INZ-QUO-00031','Zo.craft','PJ1034 - Zo Craft, Trion KL','6012-394 9194'],['INZ-QUO-00032','Xenos Fam','PJ1030 - Xenos Fam, St Marco Park Kulai','609050 8646'],['INZ-QUO-00033','Wendy Low','PJ1038 - Wendy Low, Senibong Cove','6016-557 6670'],['INZ-QUO-00034','Alys Lim','PJ1032 - Alys Lim, Horizon Hills','6011-1177 7154'],['INZ-QUO-00039','Infinite Office','PJ1040 - Infinite Office, Mount Austin','6013-740 8836'],['INZ-QUO-00039-INZ-VO-000012','Infinite Office','PJ1040 - Infinite Office, Mount Austin','6013-740 8836'],['INZ-QUO-00040','Xiao Liang','PJ1039 - Xiao Liang, Tate Dalton','6016-757 4758'],['INZ-QUO-00041','Jackson','PJ1037 - Jackson, Senibong Cove','609138 9156'],['INZ-QUO-00053','Kris','PJ1041 - Kris','6017-248 2258'],['INZ-QUO-00059','Wendy Low','PJ1038 - Wendy Low, Senibong Cove','6016-557 6670'],['INZ-QUO-00062','Aaron','PJ1042 - Aaron, Leather Code, Menara Pelangi','6012-767 6610'],['INZ-QUO-00063','Aaron','PJ1042 - Aaron, Leather Code, Menara Pelangi','6012-767 6610'],['INZ-QUO-00069','AA HAIR GROUP SDN BHD','PJ1054 - A&A Hair Studio','6013-889 8913'],['INZ-QUO-00073','One More Fitness','PJ1045 - One More Fitness','6013-509 5968'],['INZ-QUO-00074','Belle','PJ1051 - Belle studio, Taman Damansara Aliff','6016-725 6208'],['INZ-QUO-00075','Bibi','PJ1044 - Bibi, Horizon Hills','6012-792 0557'],['INZ-QUO-00077','Aidil','PJ1043 - Abdullah, Adda Height Greystone','609092 1616'],['INZ-QUO-00080','Yeong','PJ1009 - Yeong\'s Family, Taman Gaya','6016-751 9003'],['INZ-QUO-00083','Abdullah','PJ1046 - Bintang Subsea','6012-245 1615'],['INZ-QUO-00084','One More Fitness','PJ1045 - One More Fitness, Taman Gaya','6013-509 5968'],['INZ-QUO-00086','GRANDMAMA KOPITIAM SDN. BHD.','PJ1047 - Moons Cafe, Bandar Dato Onn','60167763617'],['INZ-QUO-00087','Venus','PJ1048 - Venus, The Crest Austin','6011-1082 1305'],['INZ-QUO-00103','Tai','PJ1049 - Tai, Jalan Harmonium','6012-718 3863'],['INZ-QUO-00106','Bibi','PJ1044 - Bibi, Horizon Hills','6012-792 0557'],['INZ-QUO-00111','Alex','PJ1050 - Alex, Senibong Cove, Lagoon Residence','6018-285 5678'],['INZ-QUO-00112','Chris','PJ1047 - Moons Cafe, Bandar Dato Onn','60167763617'],['INZ-QUO-00114','Henry','PJ1053 - Henry, Sunway Lenang','6019-747 0200'],['INZ-QUO-00119','Ning','PJ1055 - Ning, Tate Dalton, Eco Botanic','6018-218 8182'],['INZ-QUO-00125','Ezpet Sdn Bhd','PJ1052 - Ez Pet booth, Kuala Lumpur','6011-13084951'],['INZ-QUO-00126','Tai','PJ1049 - Tai, Jalan Harmonium','6012-718 3863'],['INZ-QUO-00127','PUSAT TUISYEN TITAN CERDIK PLT','PJ1056 - Pusat Tuisyen Titan, Setia Indah Artiz','609006 6866'],['INZ-QUO-00132','Qian Yin','PJ1057 - Qian Yin, Crest Austin Sapphire','6016-776 7790'],['INZ-QUO-00133','AA HAIR GROUP SDN BHD','PJ1054 - A&A Hair Studio','6013-889 8913'],['INZ-QUO-00138','Henry','PJ1053 - Henry, Sunway Lenang','6019-747 0200'],['INZ-QUO-00139','Ning','PJ1055 - Ning, Tate Dalton, Eco Botanic','6018-218 8182'],['INZ-QUO-00140','PUSAT TUISYEN TITAN CERDIK PLT','PJ1056 - Pusat Tuisyen Titan, Setia Indah Artiz','609006 6866'],['INZ-QUO-00142','Jia Min','PJ1059 - Jia Min, Attleborough, Eco Botanic','6016-786 3738'],['INZ-QUO-00143','Boo Kar Yuan','PJ1060 - Boo Kar Yuan, Attleborough, Eco Botanic','6011-1213 0802'],['INZ-QUO-00146','Jessy','PJ1063 - Jessy, Forte Ekoflora','6019 728 6852'],['INZ-QUO-00149','Henry','PJ1061 - Henry, Eco Botanic','6019-775 9012'],['INZ-QUO-00150','Hui Loon','PJ1058 - Hui Loon & Alex, Tate Callington, Eco Botanic','6014-617 6628'],['INZ-QUO-00158','ZOCRAFT SDN BHD','Unifi Service Zo Craft JB','6011-1270 1070'],['INZ-QUO-00159','Allan','PJ1062 - Allan, Ulu Tiram','6019-753 7370'],['INZ-QUO-00162','Qian Yin','PJ1057 - Qian Yin, Crest Austin Sapphire','6016-776 7790'],['INZ-QUO-00167','An An','PJ1064 - An An, Desa Tebrau','6010-666 8612'],['INZ-QUO-00171','Hui Loon','PJ1058 - Hui Loon & Alex, Tate Callington, Eco Botanic','6014-617 6628'],['INZ-QUO-00173','Hey Luck Fruits & Vegetables','PJ1065 - Hey Luck Fruits & Vegetables, Taman Molek','6012-792 0557'],['INZ-QUO-00175','Henry','PJ1061 - Henry, Eco Botanic','6019-775 9012'],['INZ-QUO-00181','Hey Luck Fruits & Vegetables','PJ1065 - Hey Luck Fruits & Vegetables, Taman Molek','6012-792 0557'],['INZ-QUO-00185','Koh Tiong Sim','PJ1069 - Ms Chuang, Pulai','608914 5347'],['INZ-QUO-00186','Jaelyn','PJ1066 - Jaelyn, Impian Emas','6016-739 3927'],['INZ-QUO-00187','Matheu Pang','PJ1067 - Matheu Pang, Eco Flora','6014-617 5321'],['INZ-QUO-00191','HEYTHREADS SDN BHD','PJ1068 - Heythreads Sdn Bhd, Austin Crest','6016-770 7873'],['INZ-QUO-00198','Joan','PJ1074 - Joan, Clarinet Tebrau','6016-738 8565'],['INZ-QUO-00202','Adrian','PJ1070 - Adrian, Senibong Cove','608819 3439'],['INZ-QUO-00205','Tai','PJ1049 - Tai, Jalan Harmonium','6012-718 3863'],['INZ-QUO-00206','HEYTHREADS SDN BHD','PJ1068 - Heythreads Sdn Bhd, Austin Crest','6016-770 7873'],['INZ-QUO-00207','Xin Er','PJ1071 - Xin Er, Eko Flora','6016 762 2299'],['INZ-QUO-00212','Huey Ping','PJ1075 - Huey Ping, Lagoon Senibong Cove','6012 761 5655'],['INZ-QUO-00218','Xiao Qi','PJ1073 - Xiao Qi, Ponderosa Callista','6016 660 0016'],['INZ-QUO-00222','Bibi','PJ1065 - Hey Luck Fruits & Vegetables, Taman Molek','6012-792 0557'],['INZ-QUO-00224','Adrian','PJ1070 - Adrian, Senibong Cove','608819 3439'],['INZ-QUO-00230','Matheu Pang','PJ1067 - Matheu, The Kingston, Eco Flora','6014-617 5321'],['INZ-QUO-00232','Xin Er','PJ1071 - Xin Er, Eko Floral','6016 762 2299'],['INZ-QUO-00238','Huey Ping','PJ1075 - Huey Ping, Lagoon Senibong Cove','6012 761 5655'],['INZ-QUO-00239','Catalina Gelato','PJ1076 - Catalina Gelato, Sunway Hotel Big Box','6016 725 3596'],['INZ-QUO-00256','Joan','PJ1074 - Joan, Clarinet Desa Tebrau','6016-738 8565'],['INZ-QUO-00257','Lawrence Ong','PJ1078 - Lawrence Ong, Senadi Hill','608912 1988'],['INZ-QUO-00258','Allan','PJ1062 - Allan, Taman Gaya','6019-753 7370'],['INZ-QUO-00269','Allison Koh','PJ1079 - Allison Koh, Lagoon Senibong Cove','6013 720 1218'],['INZ-QUO-00281','Allan','PJ1062 - Allan, Taman Gaya','6019-753 7370'],['INZ-QUO-00283','Zo.craft','Unifi Service Zo Craft JB','6012-394 9194'],['INZ-QUO-00286','Mr Ho','PJ1084 - Mr Ho, Eco Tropics','6014 614 7877'],['INZ-QUO-00294','Tai','PJ1049 - Tai, Jalan Harmonium','6012-718 3863'],['INZ-QUO-00295','Dews Lim','PJ1085 - Dews Lim, Eco Botanic','6012-746 5180'],['INZ-QUO-00296','Infinite EPC','PJ1086 - Infinite EPC','60378460280'],['INZ-QUO-00298','Allison Koh','PJ1079 - Allison Koh, Lagoon Senibong Cove','6013 720 1218'],['INZ-QUO-00317','Allison Koh','PJ1079 - Allison Koh, Lagoon Senibong Cove -','6013 720 1218'],['INZ-QUO-ZOCRAFT','Zo.craft','Unifi Service Zo Craft JB',''],['INZ-QUO-DP0069','Koon Tar','DP0069 - Koon Tar, Horizon Hills',''] ]; stubs.forEach(([id,cl,rem,ph])=>{ if(!findQ(id)){ _ql.push({id,quotNo:id,revision:0,client:cl,clientPhone:ph,remarks:rem, status:'Completed',date:'',wonDeal:'',tag:'',finalAmt:0,totalAmt:0, totalDisc:0,taxAmt:0,handler:'',paymentTerm:'',termCondition:'', designAgreement:'',sections:[],pis:[],payments:[], createdAt:new Date().toISOString()}); chg=true; } }); // โ”€โ”€ Payment records โ”€โ”€ const pays=[ {qn:'INZ-QUO-00313',rn:'INZ-R-00268',st:2,am:75750.0,dt:'2026-06-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00279',rn:'INZ-R-00267',st:3,am:51000.0,dt:'2026-06-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00287',rn:'INZ-R-00266',st:3,am:70000.0,dt:'2026-06-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00293',rn:'INZ-R-00264',st:3,am:8000.0,dt:'2026-06-02',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00319',rn:'INZ-R-00265',st:1,am:10500.0,dt:'2026-06-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00285',rn:'INZ-R-00262',st:1,am:6000.0,dt:'2026-05-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00275',rn:'INZ-R-00263',st:1,am:10000.0,dt:'2026-05-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00301',rn:'INZ-R-00261',st:1,am:6000.0,dt:'2026-05-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00286',rn:'INZ-R-00260',st:3,am:6700.0,dt:'2026-05-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00317',rn:'INZ-R-00259',st:1,am:2570.5,dt:'2026-05-06',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00287',rn:'INZ-R-00258',st:2,am:30000.0,dt:'2026-05-04',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00295',rn:'INZ-R-00256',st:1,am:3800.0,dt:'2026-05-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00298',rn:'INZ-R-00254',st:4,am:14291.0,dt:'2026-05-02',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00313',rn:'INZ-R-00255',st:1,am:101000.0,dt:'2026-05-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00256',rn:'INZ-R-00251',st:4,am:22222.0,dt:'2026-04-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00306',rn:'INZ-R-00250',st:1,am:256500.0,dt:'2026-04-18',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00287',rn:'INZ-R-00253',st:2,am:44100.0,dt:'2026-04-16',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00267',rn:'INZ-R-00249',st:1,am:10000.0,dt:'2026-04-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00257',rn:'INZ-R-00252',st:3,am:3800.0,dt:'2026-04-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00279',rn:'INZ-R-00248',st:2,am:77400.0,dt:'2026-03-27',me:'Cash',tx:''},{qn:'INZ-QUO-00298',rn:'INZ-R-00247',st:1,am:26000.0,dt:'2026-03-26',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00296',rn:'INZ-R-00246',st:1,am:12000.0,dt:'2026-03-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00298',rn:'INZ-R-00245',st:1,am:39000.0,dt:'2026-03-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00204',rn:'INZ-R-00257',st:2,am:385000.0,dt:'2026-02-14',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00214',rn:'INZ-R-00244',st:3,am:109000.0,dt:'2026-02-13',me:'Cheque',tx:''},{qn:'INZ-QUO-00298',rn:'INZ-R-00243',st:1,am:52000.0,dt:'2026-02-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00159',rn:'INZ-R-00242',st:3,am:5000.0,dt:'2026-02-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00256',rn:'INZ-R-00241',st:2,am:31404.0,dt:'2026-02-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00269',rn:'INZ-R-00239',st:3,am:2550.0,dt:'2026-01-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00294',rn:'INZ-R-00240',st:1,am:3921.0,dt:'2026-01-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00230',rn:'INZ-R-00238',st:4,am:37150.0,dt:'2026-01-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00224',rn:'INZ-R-00237',st:4,am:21690.0,dt:'2026-01-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00198',rn:'INZ-R-00236',st:3,am:500.0,dt:'2026-01-22',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00295',rn:'INZ-R-00235',st:1,am:4750.0,dt:'2026-01-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00286',rn:'INZ-R-00234',st:1,am:6800.0,dt:'2026-01-17',me:'Cash',tx:''},{qn:'INZ-QUO-00260',rn:'INZ-R-00233',st:1,am:17313.0,dt:'2026-01-16',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00281',rn:'INZ-R-00232',st:1,am:13640.0,dt:'2026-01-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00293',rn:'INZ-R-00231',st:1,am:8000.0,dt:'2025-12-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00287',rn:'INZ-R-00230',st:1,am:48800.0,dt:'2025-12-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00232',rn:'INZ-R-00229',st:4,am:10897.0,dt:'2025-12-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00258',rn:'INZ-R-00228',st:1,am:38799.5,dt:'2025-12-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00287',rn:'INZ-R-00227',st:1,am:50000.0,dt:'2025-12-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00279',rn:'INZ-R-00226',st:1,am:103200.0,dt:'2025-12-24',me:'Cash',tx:''},{qn:'INZ-QUO-00230',rn:'INZ-R-00225',st:3,am:42800.0,dt:'2025-12-17',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00283',rn:'INZ-R-00224',st:1,am:2023.57,dt:'2025-12-11',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00278',rn:'INZ-R-00223',st:1,am:7500.0,dt:'2025-12-11',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00221',st:4,am:14000.0,dt:'2025-12-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00239',rn:'INZ-R-00222',st:3,am:4000.0,dt:'2025-12-08',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00220',st:4,am:20111.5,dt:'2025-12-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00185',rn:'INZ-R-00219',st:3,am:5400.0,dt:'2025-11-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00218',rn:'INZ-R-00218',st:3,am:4750.0,dt:'2025-11-25',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00217',st:4,am:8000.0,dt:'2025-11-25',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00269',rn:'INZ-R-00216',st:1,am:4250.0,dt:'2025-11-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00215',st:4,am:8000.0,dt:'2025-11-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00214',st:4,am:4800.0,dt:'2025-11-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00256',rn:'INZ-R-00213',st:1,am:31404.0,dt:'2025-11-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00224',rn:'INZ-R-00212',st:3,am:44000.0,dt:'2025-11-18',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00202',rn:'INZ-R-00211',st:3,am:3800.0,dt:'2025-11-18',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00264',rn:'INZ-R-00210',st:1,am:206100.0,dt:'2025-11-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00204',rn:'INZ-R-00208',st:2,am:300000.0,dt:'2025-11-06',me:'Cash',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00209',st:2,am:32000.0,dt:'2025-10-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00257',rn:'INZ-R-00207',st:1,am:4750.0,dt:'2025-10-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00206',st:1,am:8000.0,dt:'2025-10-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00230',rn:'INZ-R-00205',st:2,am:64200.0,dt:'2025-10-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00232',rn:'INZ-R-00204',st:3,am:47814.0,dt:'2025-10-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00258',rn:'INZ-R-00203',st:1,am:24020.0,dt:'2025-10-16',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00224',rn:'INZ-R-00202',st:2,am:66000.0,dt:'2025-09-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00201',st:1,am:10000.0,dt:'2025-09-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00214',rn:'INZ-R-00200',st:2,am:109500.0,dt:'2025-09-25',me:'Cheque',tx:''},{qn:'INZ-QUO-00238',rn:'INZ-R-00199',st:1,am:33400.0,dt:'2025-09-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00212',rn:'INZ-R-00198',st:3,am:2600.0,dt:'2025-09-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00245',rn:'INZ-R-00197',st:1,am:4750.0,dt:'2025-09-22',me:'Cash',tx:''},{qn:'INZ-QUO-00175',rn:'INZ-R-00196',st:4,am:20587.26,dt:'2025-09-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00186',rn:'INZ-R-00195',st:3,am:3750.0,dt:'2025-09-17',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00204',rn:'INZ-R-00194',st:2,am:30000.0,dt:'2025-09-16',me:'Cash',tx:''},{qn:'INZ-QUO-00232',rn:'INZ-R-00193',st:2,am:71721.0,dt:'2025-09-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00204',rn:'INZ-R-00192',st:2,am:100000.0,dt:'2025-08-29',me:'Cash',tx:''},{qn:'INZ-QUO-00190',rn:'INZ-R-00191',st:3,am:65600.0,dt:'2025-08-12',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00232',rn:'INZ-R-00190',st:1,am:95628.0,dt:'2025-08-08',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00239',rn:'INZ-R-00189',st:1,am:4000.0,dt:'2025-08-04',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00207',rn:'INZ-R-00188',st:3,am:3800.0,dt:'2025-07-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00162',rn:'INZ-R-00187',st:4,am:39174.4,dt:'2025-07-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00230',rn:'INZ-R-00186',st:1,am:85600.0,dt:'2025-07-14',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00204',rn:'INZ-R-00185',st:1,am:288750.0,dt:'2025-07-07',me:'Cash',tx:''},{qn:'INZ-QUO-00146',rn:'INZ-R-00184',st:3,am:11250.0,dt:'2025-07-07',me:'Cash',tx:''},{qn:'INZ-QUO-00190',rn:'INZ-R-00183',st:2,am:98400.0,dt:'2025-06-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00171',rn:'INZ-R-00181',st:4,am:28500.0,dt:'2025-06-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00142',rn:'INZ-R-00182',st:3,am:3800.0,dt:'2025-06-26',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00224',rn:'INZ-R-00180',st:1,am:88000.0,dt:'2025-06-26',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00222',rn:'INZ-R-00179',st:1,am:800.0,dt:'2025-06-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00206',rn:'INZ-R-00178',st:4,am:40008.0,dt:'2025-06-11',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00143',rn:'INZ-R-00177',st:3,am:4750.0,dt:'2025-06-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00175',rn:'INZ-R-00176',st:3,am:51791.72,dt:'2025-05-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00175',st:4,am:15000.0,dt:'2025-05-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00212',rn:'INZ-R-00174',st:1,am:3250.0,dt:'2025-05-14',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00198',rn:'INZ-R-00173',st:1,am:500.0,dt:'2025-05-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00218',rn:'INZ-R-00172',st:1,am:4750.0,dt:'2025-05-06',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00207',rn:'INZ-R-00171',st:1,am:4750.0,dt:'2025-05-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00139',rn:'INZ-R-00170',st:4,am:31300.0,dt:'2025-04-30',me:'Cash',tx:''},{qn:'INZ-QUO-00204',rn:'INZ-R-00169',st:1,am:200000.0,dt:'2025-04-29',me:'Cash',tx:''},{qn:'INZ-QUO-00214',rn:'INZ-R-00168',st:1,am:146000.0,dt:'2025-04-25',me:'Cheque',tx:''},{qn:'INZ-QUO-00206',rn:'INZ-R-00167',st:2,am:40950.0,dt:'2025-04-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00191',rn:'INZ-R-00166',st:3,am:3150.0,dt:'2025-04-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00181',rn:'INZ-R-00165',st:4,am:19708.79,dt:'2025-04-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00206',rn:'INZ-R-00164',st:1,am:54600.0,dt:'2025-04-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00162',rn:'INZ-R-00163',st:3,am:43516.0,dt:'2025-03-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00205',rn:'INZ-R-00162',st:1,am:800.0,dt:'2025-03-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00161',st:4,am:30000.0,dt:'2025-03-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00202',rn:'INZ-R-00160',st:1,am:4750.0,dt:'2025-03-26',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00175',rn:'INZ-R-00159',st:2,am:81271.02,dt:'2025-03-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00185',rn:'INZ-R-00158',st:1,am:6750.0,dt:'2025-03-14',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00171',rn:'INZ-R-00157',st:3,am:45600.0,dt:'2025-03-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00132',rn:'INZ-R-00156',st:3,am:5000.0,dt:'2025-03-02',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00190',rn:'INZ-R-00155',st:1,am:131200.0,dt:'2025-03-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00181',rn:'INZ-R-00154',st:2,am:23700.0,dt:'2025-02-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00191',rn:'INZ-R-00153',st:1,am:5250.0,dt:'2025-02-25',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00152',st:3,am:60000.0,dt:'2025-02-25',me:'Cash',tx:''},{qn:'INZ-QUO-00187',rn:'INZ-R-00151',st:1,am:4750.0,dt:'2025-02-12',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00173',rn:'INZ-R-00150',st:3,am:5175.0,dt:'2025-02-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00181',rn:'INZ-R-00149',st:1,am:31600.0,dt:'2025-02-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00162',rn:'INZ-R-00148',st:2,am:65274.0,dt:'2025-01-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00140',rn:'INZ-R-00147',st:4,am:14788.0,dt:'2025-01-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00171',rn:'INZ-R-00146',st:2,am:18400.0,dt:'2025-01-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00171',rn:'INZ-R-00145',st:2,am:50000.0,dt:'2025-01-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00186',rn:'INZ-R-00144',st:1,am:6250.0,dt:'2025-01-17',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00041',rn:'INZ-R-00143',st:4,am:25000.0,dt:'2024-12-30',me:'Cheque',tx:''},{qn:'INZ-QUO-00175',rn:'INZ-R-00142',st:1,am:60000.0,dt:'2024-12-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00126',rn:'INZ-R-00141',st:4,am:63800.0,dt:'2024-12-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00175',rn:'INZ-R-00140',st:1,am:40000.0,dt:'2024-12-18',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00139',st:2,am:150000.0,dt:'2024-12-18',me:'Cash',tx:''},{qn:'INZ-QUO-00139',rn:'INZ-R-00138',st:3,am:51000.0,dt:'2024-12-14',me:'Cash',tx:''},{qn:'INZ-QUO-00133',rn:'INZ-R-00137',st:4,am:4710.0,dt:'2024-12-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00136',st:2,am:94000.0,dt:'2024-11-25',me:'Cash',tx:''},{qn:'INZ-QUO-00114',rn:'INZ-R-00135',st:3,am:6000.0,dt:'2024-11-25',me:'Cash',tx:''},{qn:'INZ-QUO-00150',rn:'INZ-R-00133',st:3,am:3800.0,dt:'2024-11-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00162',rn:'INZ-R-00134',st:1,am:87032.0,dt:'2024-11-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00171',rn:'INZ-R-00132',st:1,am:91200.0,dt:'2024-11-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00140',rn:'INZ-R-00131',st:3,am:50000.0,dt:'2024-11-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00111',rn:'INZ-R-00130',st:3,am:6250.0,dt:'2024-11-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00139',rn:'INZ-R-00129',st:2,am:76500.0,dt:'2024-11-07',me:'Cash',tx:''},{qn:'INZ-QUO-00167',rn:'INZ-R-00128',st:1,am:7500.0,dt:'2024-11-05',me:'Cash',tx:''},{qn:'INZ-QUO-00126',rn:'INZ-R-00127',st:3,am:71600.0,dt:'2024-10-21',me:'Cheque',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00125',st:1,am:50000.0,dt:'2024-10-14',me:'Cash',tx:''},{qn:'INZ-QUO-00074',rn:'INZ-R-00124',st:3,am:3000.0,dt:'2024-10-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00017',rn:'INZ-R-00123',st:3,am:3954.0,dt:'2024-10-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00159',rn:'INZ-R-00122',st:1,am:6250.0,dt:'2024-09-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00158',rn:'INZ-R-00126',st:1,am:1768.2,dt:'2024-09-25',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00140',rn:'INZ-R-00121',st:2,am:90000.0,dt:'2024-09-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00127',rn:'INZ-R-00120',st:3,am:6300.0,dt:'2024-09-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00149',rn:'INZ-R-00119',st:1,am:8550.0,dt:'2024-09-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00143',rn:'INZ-R-00118',st:1,am:4750.0,dt:'2024-09-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00126',rn:'INZ-R-00117',st:2,am:107400.0,dt:'2024-09-09',me:'Cheque',tx:''},{qn:'INZ-QUO-00106',rn:'INZ-R-00116',st:4,am:18730.0,dt:'2024-09-08',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00142',rn:'INZ-R-00115',st:1,am:4750.0,dt:'2024-09-06',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00150',rn:'INZ-R-00114',st:1,am:4750.0,dt:'2024-09-04',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00140',rn:'INZ-R-00113',st:1,am:120000.0,dt:'2024-09-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00133',rn:'INZ-R-00112',st:1,am:4000.0,dt:'2024-08-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00069',rn:'INZ-R-00111',st:3,am:4600.0,dt:'2024-08-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00087',rn:'INZ-R-00110',st:3,am:8100.0,dt:'2024-08-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00077',rn:'INZ-R-00109',st:2,am:8000.0,dt:'2024-08-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00139',rn:'INZ-R-00108',st:1,am:102000.0,dt:'2024-08-15',me:'Cash',tx:''},{qn:'INZ-QUO-00063',rn:'INZ-R-00107',st:4,am:20550.0,dt:'2024-08-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00138',rn:'INZ-R-00106',st:1,am:150000.0,dt:'2024-08-10',me:'Cash',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00105',st:4,am:5000.0,dt:'2024-08-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00104',st:4,am:5000.0,dt:'2024-08-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00040',rn:'INZ-R-00103',st:3,am:4750.0,dt:'2024-08-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00125',rn:'INZ-R-00102',st:1,am:2000.0,dt:'2024-07-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00106',rn:'INZ-R-00101',st:3,am:38946.79,dt:'2024-07-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00132',rn:'INZ-R-00100',st:1,am:6250.0,dt:'2024-07-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00099',st:4,am:7734.5,dt:'2024-07-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00016',rn:'INZ-R-00098',st:3,am:3537.0,dt:'2024-07-22',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00106',rn:'INZ-R-00097',st:2,am:53053.21,dt:'2024-06-26',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00103',rn:'INZ-R-00096',st:3,am:3800.0,dt:'2024-06-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00126',rn:'INZ-R-00095',st:1,am:143200.0,dt:'2024-06-20',me:'Cheque',tx:''},{qn:'INZ-QUO-00084',rn:'INZ-R-00094',st:4,am:27722.5,dt:'2024-06-12',me:'Cheque',tx:''},{qn:'INZ-QUO-00073',rn:'INZ-R-00093',st:3,am:6460.0,dt:'2024-06-12',me:'Cheque',tx:''},{qn:'INZ-QUO-00053',rn:'INZ-R-00092',st:1,am:7500.0,dt:'2024-06-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00127',rn:'INZ-R-00091',st:1,am:7875.0,dt:'2024-06-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00063',rn:'INZ-R-00090',st:2,am:18000.0,dt:'2024-05-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00034',rn:'INZ-R-00089',st:4,am:17766.1,dt:'2024-05-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00088',st:3,am:12979.0,dt:'2024-05-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00119',rn:'INZ-R-00087',st:2,am:8550.0,dt:'2024-05-23',me:'Cash',tx:''},{qn:'INZ-QUO-00112',rn:'INZ-R-00086',st:3,am:2800.0,dt:'2024-05-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00085',st:3,am:10000.0,dt:'2024-05-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00069',rn:'INZ-R-00084',st:1,am:5000.0,dt:'2024-05-17',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00114',rn:'INZ-R-00083',st:1,am:7500.0,dt:'2024-05-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00063',rn:'INZ-R-00082',st:1,am:24000.0,dt:'2024-05-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00062',rn:'INZ-R-00081',st:3,am:2576.0,dt:'2024-05-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00083',rn:'INZ-R-00080',st:3,am:1000.0,dt:'2024-05-14',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00079',st:3,am:10000.0,dt:'2024-05-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00074',rn:'INZ-R-00078',st:1,am:3000.0,dt:'2024-05-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00041',rn:'INZ-R-00077',st:3,am:43000.0,dt:'2024-05-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00111',rn:'INZ-R-00076',st:1,am:6250.0,dt:'2024-05-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00106',rn:'INZ-R-00075',st:1,am:70000.0,dt:'2024-04-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00084',rn:'INZ-R-00074',st:2,am:19200.0,dt:'2024-04-24',me:'Cheque',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00072',st:2,am:17826.5,dt:'2024-04-22',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00071',st:2,am:10000.0,dt:'2024-04-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00103',rn:'INZ-R-00070',st:1,am:4750.0,dt:'2024-04-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00039-INZ-VO-000012',rn:'INZ-R-00069',st:1,am:14255.0,dt:'2024-04-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00068',st:2,am:10000.0,dt:'2024-04-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00087',rn:'INZ-R-00067',st:1,am:6400.0,dt:'2024-04-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00066',st:2,am:10000.0,dt:'2024-04-01',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00086',rn:'INZ-R-00065',st:1,am:4000.0,dt:'2024-03-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00041',rn:'INZ-R-00064',st:2,am:64500.0,dt:'2024-03-28',me:'Cheque',tx:''},{qn:'INZ-QUO-00039',rn:'INZ-R-00063',st:4,am:33000.0,dt:'2024-03-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00084',rn:'INZ-R-00062',st:1,am:25600.0,dt:'2024-03-23',me:'Cheque',tx:''},{qn:'INZ-QUO-00080',rn:'INZ-R-00073',st:1,am:800.0,dt:'2024-03-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00032',rn:'INZ-R-00061',st:4,am:29090.0,dt:'2024-03-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00060',st:1,am:10000.0,dt:'2024-03-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00083',rn:'INZ-R-00058',st:1,am:1000.0,dt:'2024-03-04',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00059',st:1,am:20000.0,dt:'2024-02-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00057',st:1,am:10000.0,dt:'2024-02-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00077',rn:'INZ-R-00056',st:1,am:5000.0,dt:'2024-02-26',me:'Cheque',tx:''},{qn:'INZ-QUO-00075',rn:'INZ-R-00055',st:3,am:7600.0,dt:'2024-02-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00026',rn:'INZ-R-00054',st:3,am:4500.0,dt:'2024-02-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00041',rn:'INZ-R-00053',st:1,am:86000.0,dt:'2024-02-07',me:'Cheque',tx:''},{qn:'INZ-QUO-00030',rn:'INZ-R-00052',st:2,am:3800.0,dt:'2024-02-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00034',rn:'INZ-R-00051',st:3,am:41065.0,dt:'2024-02-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00015',rn:'INZ-R-00050',st:3,am:7500.0,dt:'2024-02-06',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00049',st:1,am:10000.0,dt:'2024-02-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00039',rn:'INZ-R-00048',st:3,am:99000.0,dt:'2024-02-02',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00062',rn:'INZ-R-00047',st:1,am:3220.0,dt:'2024-01-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00027',rn:'INZ-R-00046',st:4,am:21900.0,dt:'2024-01-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00059',rn:'INZ-R-00045',st:1,am:17600.0,dt:'2024-01-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00033',rn:'INZ-R-00044',st:3,am:3800.0,dt:'2024-01-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00039',rn:'INZ-R-00043',st:2,am:99000.0,dt:'2024-01-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00034',rn:'INZ-R-00042',st:2,am:50000.0,dt:'2024-01-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00032',rn:'INZ-R-00041',st:3,am:49980.0,dt:'2023-12-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00053',rn:'INZ-R-00040',st:1,am:7500.0,dt:'2023-12-25',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00007',rn:'INZ-R-00039',st:4,am:5700.0,dt:'2023-12-11',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00032',rn:'INZ-R-00037',st:2,am:62930.0,dt:'2023-12-06',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00039',rn:'INZ-R-00038',st:1,am:99000.0,dt:'2023-12-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00040',rn:'INZ-R-00036',st:1,am:4750.0,dt:'2023-11-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00014',rn:'INZ-R-00035',st:4,am:14640.0,dt:'2023-11-02',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00001',rn:'INZ-R-00033',st:2,am:1611.0,dt:'2023-10-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00007',rn:'INZ-R-00034',st:3,am:51950.0,dt:'2023-10-29',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00033',rn:'INZ-R-00032',st:1,am:4750.0,dt:'2023-10-26',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00027',rn:'INZ-R-00031',st:3,am:38000.0,dt:'2023-10-10',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00034',rn:'INZ-R-00030',st:1,am:87200.0,dt:'2023-10-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00034',rn:'INZ-R-00027',st:1,am:250.0,dt:'2023-10-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00013',rn:'INZ-R-00026',st:1,am:2850.0,dt:'2023-10-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00030',rn:'INZ-R-00025',st:1,am:4750.0,dt:'2023-09-30',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00014',rn:'INZ-R-00022',st:3,am:25000.0,dt:'2023-09-23',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00031',rn:'INZ-R-00023',st:1,am:57735.0,dt:'2023-09-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00014',rn:'INZ-R-00021',st:2,am:3680.0,dt:'2023-09-20',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00027',rn:'INZ-R-00029',st:2,am:26500.0,dt:'2023-09-09',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00026',rn:'INZ-R-00019',st:1,am:5000.0,dt:'2023-09-08',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00027',rn:'INZ-R-00028',st:2,am:26500.0,dt:'2023-09-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00032',rn:'INZ-R-00020',st:1,am:112000.0,dt:'2023-09-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00009',rn:'INZ-R-00024',st:1,am:3800.0,dt:'2023-08-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00008',rn:'INZ-R-00018',st:2,am:3800.0,dt:'2023-08-31',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00017',rn:'INZ-R-00016',st:1,am:6590.0,dt:'2023-08-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00016',rn:'INZ-R-00015',st:1,am:5895.0,dt:'2023-08-24',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00015',rn:'INZ-R-00013',st:1,am:5000.0,dt:'2023-08-04',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00014',rn:'INZ-R-00012',st:1,am:27200.0,dt:'2023-07-13',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00010',rn:'INZ-R-00011',st:3,am:7650.0,dt:'2023-07-07',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00027',rn:'INZ-R-00017',st:1,am:80000.0,dt:'2023-07-03',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00007',rn:'INZ-R-00010',st:2,am:46200.0,dt:'2023-06-27',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00013',rn:'INZ-R-00014',st:1,am:4750.0,dt:'2023-06-19',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00009',rn:'INZ-R-00008',st:1,am:4750.0,dt:'2023-05-16',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00003',rn:'INZ-R-00006',st:3,am:5500.0,dt:'2023-05-05',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00008',rn:'INZ-R-00007',st:1,am:4750.0,dt:'2023-04-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00002',rn:'INZ-R-00005',st:3,am:4000.0,dt:'2023-04-05',me:'Cash',tx:''},{qn:'INZ-QUO-00007',rn:'INZ-R-00009',st:1,am:61600.0,dt:'2023-03-28',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00004',rn:'INZ-R-00003',st:1,am:700.0,dt:'2023-02-21',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00003',rn:'INZ-R-00004',st:1,am:5500.0,dt:'2023-02-15',me:'Bank Transfer',tx:''},{qn:'INZ-QUO-00002',rn:'INZ-R-00002',st:1,am:5000.0,dt:'2023-01-10',me:'Cash',tx:''},{qn:'INZ-QUO-00001',rn:'INZ-R-00001',st:1,am:4029.0,dt:'2023-01-02',me:'Bank Transfer',tx:''} ]; pays.forEach(p=>{ const q=findQ(p.qn);if(!q)return; if(!q.payments)q.payments=[]; if(q.payments.some(x=>x.rcpNo===p.rn))return; q.payments.push({id:uid(),rcpNo:p.rn,stageNo:p.st,stageLabel:'Stage '+p.st, description:'Payment for '+p.qn,amount:p.am,date:p.dt,method:p.me, transactionNo:p.tx,badDebt:false,bank:'',remarks:'', createdAt:new Date().toISOString()}); chg=true; }); // โ”€โ”€ Invoice records โ”€โ”€ const invs=[ {qn:'INZ-QUO-00293',pj:'PJ1081',in:'INZ-INV-00095',am:16000.0,st:'In progress'},{qn:'INZ-QUO-00286',pj:'PJ1084',in:'INZ-INV-00094',am:13500.0,st:'Completed'},{qn:'INZ-QUO-00269',pj:'PJ1079',in:'INZ-INV-00093',am:2570.5,st:'Completed'},{qn:'INZ-QUO-00295',pj:'PJ1085',in:'INZ-INV-00092',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00269',pj:'PJ1079',in:'INZ-INV-00091',am:131291.0,st:'Completed'},{qn:'INZ-QUO-00257',pj:'PJ1078',in:'INZ-INV-00090',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00198',pj:'PJ1074',in:'INZ-INV-00089',am:85030.0,st:'Completed'},{qn:'INZ-QUO-00296',pj:'PJ1086',in:'INZ-INV-00088',am:12000.0,st:'Completed'},{qn:'INZ-QUO-00159',pj:'PJ1062',in:'INZ-INV-00087',am:11250.0,st:'Completed'},{qn:'INZ-QUO-00103',pj:'PJ1049',in:'INZ-INV-00086',am:3921.0,st:'Completed'},{qn:'INZ-QUO-00269',pj:'PJ1079',in:'INZ-INV-00085',am:6800.0,st:'Completed'},{qn:'INZ-QUO-00187',pj:'PJ1067',in:'INZ-INV-00084',am:229750.0,st:'Completed'},{qn:'INZ-QUO-00202',pj:'PJ1070',in:'INZ-INV-00083',am:219690.0,st:'Completed'},{qn:'INZ-QUO-00198',pj:'PJ1074',in:'INZ-INV-00082',am:1000.0,st:'Completed'},{qn:'INZ-QUO-00159',pj:'PJ1062',in:'INZ-INV-00081',am:13640.0,st:'Completed'},{qn:'INZ-QUO-00207',pj:'PJ1071',in:'INZ-INV-00080',am:226060.0,st:'Completed'},{qn:'INZ-QUO-00159',pj:'PJ1062',in:'INZ-INV-00079',am:62819.5,st:'Completed'},{qn:'INZ-QUO-ZOCRAFT',pj:'',in:'INZ-INV-00078',am:2023.57,st:'Completed'},{qn:'INZ-QUO-00239',pj:'PJ1076',in:'INZ-INV-00077',am:8000.0,st:'Completed'},{qn:'INZ-QUO-00212',pj:'PJ1075',in:'INZ-INV-00076',am:133511.5,st:'Completed'},{qn:'INZ-QUO-00185',pj:'PJ1069',in:'INZ-INV-00075',am:12150.0,st:'Completed'},{qn:'INZ-QUO-00218',pj:'PJ1073',in:'INZ-INV-00074',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00114',pj:'PJ1053',in:'INZ-INV-00073',am:553800.0,st:'Completed'},{qn:'INZ-QUO-00202',pj:'PJ1070',in:'INZ-INV-00072',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00187',pj:'PJ1067',in:'INZ-INV-00071',am:4750.0,st:'Completed'},{qn:'INZ-QUO-00212',pj:'PJ1075',in:'INZ-INV-00070',am:5850.0,st:'Completed'},{qn:'INZ-QUO-00149',pj:'PJ1061',in:'INZ-INV-00069',am:253650.0,st:'Completed'},{qn:'INZ-QUO-00186',pj:'PJ1066',in:'INZ-INV-00068',am:10000.0,st:'Completed'},{qn:'INZ-QUO-00207',pj:'PJ1071',in:'INZ-INV-00067',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00132',pj:'PJ1057',in:'INZ-INV-00066',am:234996.4,st:'Completed'},{qn:'INZ-QUO-00204',pj:'PJ1063',in:'INZ-INV-00065',am:11250.0,st:'Completed'},{qn:'INZ-QUO-00167',pj:'PJ1064',in:'INZ-INV-00064',am:7500.0,st:'Completed'},{qn:'INZ-QUO-00142',pj:'PJ1059',in:'INZ-INV-00063',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00150',pj:'PJ1058',in:'INZ-INV-00062',am:233700.0,st:'Completed'},{qn:'INZ-QUO-00181',pj:'PJ1065',in:'INZ-INV-00061',am:800.0,st:'Completed'},{qn:'INZ-QUO-00191',pj:'PJ1068',in:'INZ-INV-00060',am:135558.0,st:'Completed'},{qn:'INZ-QUO-00143',pj:'PJ1060',in:'INZ-INV-00059',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00119',pj:'PJ1055',in:'INZ-INV-00058',am:260800.0,st:'Completed'},{qn:'INZ-QUO-00191',pj:'PJ1068',in:'INZ-INV-00057',am:8400.0,st:'Completed'},{qn:'INZ-QUO-00181',pj:'PJ1065',in:'INZ-INV-00056',am:75008.79,st:'Completed'},{qn:'INZ-QUO-00103',pj:'PJ1049',in:'INZ-INV-00055',am:800.0,st:'Completed'},{qn:'INZ-QUO-00132',pj:'PJ1057',in:'INZ-INV-00054',am:11250.0,st:'Completed'},{qn:'INZ-QUO-00181',pj:'PJ1065',in:'INZ-INV-00053',am:5175.0,st:'Completed'},{qn:'INZ-QUO-00127',pj:'PJ1056',in:'INZ-INV-00052',am:274788.0,st:'Completed'},{qn:'INZ-QUO-00030',pj:'PJ1037',in:'INZ-INV-00051',am:218500.0,st:'Completed'},{qn:'INZ-QUO-00103',pj:'PJ1049',in:'INZ-INV-00050',am:386000.0,st:'Completed'},{qn:'INZ-QUO-00149',pj:'PJ1061',in:'INZ-INV-00049',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00069',pj:'PJ1054',in:'INZ-INV-00048',am:8710.0,st:'Completed'},{qn:'INZ-QUO-00114',pj:'PJ1053',in:'INZ-INV-00047',am:13500.0,st:'Completed'},{qn:'INZ-QUO-00150',pj:'PJ1058',in:'INZ-INV-00046',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00111',pj:'PJ1050',in:'INZ-INV-00045',am:12500.0,st:'Completed'},{qn:'INZ-QUO-ZOCRAFT',pj:'',in:'INZ-INV-00044',am:1768.2,st:'Completed'},{qn:'INZ-QUO-00074',pj:'PJ1051',in:'INZ-INV-00043',am:6000.0,st:'Completed'},{qn:'INZ-QUO-00127',pj:'PJ1056',in:'INZ-INV-00042',am:14175.0,st:'Completed'},{qn:'INZ-QUO-00075',pj:'PJ1044',in:'INZ-INV-00041',am:180730.0,st:'Completed'},{qn:'INZ-QUO-00069',pj:'PJ1054',in:'INZ-INV-00040',am:9600.0,st:'Completed'},{qn:'INZ-QUO-00087',pj:'PJ1048',in:'INZ-INV-00039',am:14500.0,st:'Completed'},{qn:'INZ-QUO-00119',pj:'PJ1055',in:'INZ-INV-00038',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00062',pj:'PJ1042',in:'INZ-INV-00037',am:62550.0,st:'Completed'},{qn:'INZ-QUO-00033',pj:'PJ1038',in:'INZ-INV-00036',am:166140.0,st:'Completed'},{qn:'INZ-QUO-00040',pj:'PJ1039',in:'INZ-INV-00035',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00125',pj:'PJ1052',in:'INZ-INV-00034',am:2000.0,st:'Completed'},{qn:'INZ-QUO-00103',pj:'PJ1049',in:'INZ-INV-00033',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00084',pj:'PJ1045',in:'INZ-INV-00032',am:72522.5,st:'Completed'},{qn:'INZ-QUO-00084',pj:'PJ1045',in:'INZ-INV-00031',am:6460.0,st:'Completed'},{qn:'INZ-QUO-00053',pj:'PJ1041',in:'INZ-INV-00030',am:15000.0,st:'Completed'},{qn:'INZ-QUO-00013',pj:'PJ1032',in:'INZ-INV-00018',am:196281.1,st:'Completed'},{qn:'INZ-QUO-00086',pj:'PJ1047',in:'INZ-INV-00029',am:4000.0,st:'Completed'},{qn:'INZ-QUO-00086',pj:'PJ1047',in:'INZ-INV-00028',am:2800.0,st:'Completed'},{qn:'INZ-QUO-00062',pj:'PJ1042',in:'INZ-INV-00027',am:5796.0,st:'Completed'},{qn:'INZ-QUO-00083',pj:'PJ1046',in:'INZ-INV-00026',am:2000.0,st:'Completed'},{qn:'INZ-QUO-00080',pj:'PJ1009',in:'INZ-INV-00025',am:800.0,st:'Completed'},{qn:'INZ-QUO-00039',pj:'PJ1040',in:'INZ-INV-00024',am:14255.0,st:'Completed'},{qn:'INZ-QUO-00077',pj:'PJ1043',in:'INZ-INV-00023',am:13000.0,st:'Completed'},{qn:'INZ-QUO-00009',pj:'PJ1030',in:'INZ-INV-00022',am:254000.0,st:'Completed'},{qn:'INZ-QUO-00075',pj:'PJ1044',in:'INZ-INV-00020',am:7600.0,st:'Completed'},{qn:'INZ-QUO-00026',pj:'PJ1036',in:'INZ-INV-00015',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00033',pj:'PJ1038',in:'INZ-INV-00021',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00001',pj:'PJ1025',in:'INZ-INV-00007',am:165450.0,st:'Completed'},{qn:'INZ-QUO-00039',pj:'PJ1040',in:'INZ-INV-00019',am:330000.0,st:'Completed'},{qn:'INZ-QUO-00030',pj:'PJ1037',in:'INZ-INV-00017',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00031',pj:'PJ1034',in:'INZ-INV-00016',am:57735.0,st:'Completed'},{qn:'INZ-QUO-00008',pj:'PJ1029',in:'INZ-INV-00014',am:192900.0,st:'Completed'},{qn:'INZ-QUO-00016',pj:'PJ1035',in:'INZ-INV-00013',am:10544.0,st:'Completed'},{qn:'INZ-QUO-00016',pj:'PJ1035',in:'INZ-INV-00012',am:9432.0,st:'Completed'},{qn:'INZ-QUO-00013',pj:'PJ1032',in:'INZ-INV-00011',am:7600.0,st:'Completed'},{qn:'INZ-QUO-00015',pj:'PJ1033',in:'INZ-INV-00010',am:12500.0,st:'Completed'},{qn:'INZ-QUO-00014',pj:'PJ1031',in:'INZ-INV-00009',am:70520.0,st:'Completed'},{qn:'INZ-QUO-DP0069',pj:'',in:'INZ-INV-00008',am:7650.0,st:'Completed'},{qn:'INZ-QUO-00009',pj:'PJ1030',in:'INZ-INV-00006',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00008',pj:'PJ1029',in:'INZ-INV-00005',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00003',pj:'PJ1027',in:'INZ-INV-00003',am:11000.0,st:'Completed'},{qn:'INZ-QUO-00004',pj:'PJ1003',in:'INZ-INV-00004',am:700.0,st:'Completed'},{qn:'INZ-QUO-00002',pj:'PJ1026',in:'INZ-INV-00002',am:9000.0,st:'Completed'},{qn:'INZ-QUO-00001',pj:'PJ1025',in:'INZ-INV-00001',am:5640.0,st:'Completed'} ]; invs.forEach(v=>{ const q=v.qn?findQ(v.qn):(v.pj?_ql.find(x=>(x.remarks||'').startsWith(v.pj)):null); if(!q)return; if(!q.invoices)q.invoices=[]; if(q.invoices.some(x=>x.invNo===v.in))return; q.invoices.push({invNo:v.in,date:'',amount:v.am,status:v.st,createdAt:new Date().toISOString()}); chg=true; }); if(chg){ localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); QUOT_LIST.length=0;QUOT_LIST.push(..._ql); localStorage.setItem('inzii_receipt_counter','268'); localStorage.setItem('inzii_invoice_counter','95'); localStorage.setItem('inzii_mig_v3','1'); console.log('[INZII] Migration v3: '+_ql.length+' quotations, payments+invoices loaded.'); } })(); // โ”€โ”€ End migration v3 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v4: convert q.invoice โ†’ q.invoices[] + re-import all 95 โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v4'))return; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); let chg=false; const findQ=baseNo=>_ql.find(q=>q.id.replace(/-R\d+$/,'')===baseNo||q.id===baseNo); // Step 1: Convert any old q.invoice (single object) to q.invoices array _ql.forEach(q=>{ if(q.invoice&&!q.invoices){ q.invoices=[q.invoice]; delete q.invoice; chg=true; } else if(q.invoice&&q.invoices){ // merge old single into array if not already there if(!q.invoices.some(x=>x.invNo===q.invoice.invNo)){ q.invoices.push(q.invoice); chg=true; } delete q.invoice; } if(!q.invoices)q.invoices=[]; }); // Step 2: Re-import all 95 invoices (fill any missing ones not yet in array) const invs=[ {qn:'INZ-QUO-00293',in:'INZ-INV-00095',am:16000.0,st:'In progress'},{qn:'INZ-QUO-00286',in:'INZ-INV-00094',am:13500.0,st:'Completed'},{qn:'INZ-QUO-00269',in:'INZ-INV-00093',am:2570.5,st:'Completed'},{qn:'INZ-QUO-00295',in:'INZ-INV-00092',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00269',in:'INZ-INV-00091',am:131291.0,st:'Completed'},{qn:'INZ-QUO-00257',in:'INZ-INV-00090',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00198',in:'INZ-INV-00089',am:85030.0,st:'Completed'},{qn:'INZ-QUO-00296',in:'INZ-INV-00088',am:12000.0,st:'Completed'},{qn:'INZ-QUO-00159',in:'INZ-INV-00087',am:11250.0,st:'Completed'},{qn:'INZ-QUO-00103',in:'INZ-INV-00086',am:3921.0,st:'Completed'},{qn:'INZ-QUO-00269',in:'INZ-INV-00085',am:6800.0,st:'Completed'},{qn:'INZ-QUO-00187',in:'INZ-INV-00084',am:229750.0,st:'Completed'},{qn:'INZ-QUO-00202',in:'INZ-INV-00083',am:219690.0,st:'Completed'},{qn:'INZ-QUO-00198',in:'INZ-INV-00082',am:1000.0,st:'Completed'},{qn:'INZ-QUO-00159',in:'INZ-INV-00081',am:13640.0,st:'Completed'},{qn:'INZ-QUO-00207',in:'INZ-INV-00080',am:226060.0,st:'Completed'},{qn:'INZ-QUO-00159',in:'INZ-INV-00079',am:62819.5,st:'Completed'},{qn:'INZ-QUO-ZOCRAFT',in:'INZ-INV-00078',am:2023.57,st:'Completed'},{qn:'INZ-QUO-00239',in:'INZ-INV-00077',am:8000.0,st:'Completed'},{qn:'INZ-QUO-00212',in:'INZ-INV-00076',am:133511.5,st:'Completed'},{qn:'INZ-QUO-00185',in:'INZ-INV-00075',am:12150.0,st:'Completed'},{qn:'INZ-QUO-00218',in:'INZ-INV-00074',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00114',in:'INZ-INV-00073',am:553800.0,st:'Completed'},{qn:'INZ-QUO-00202',in:'INZ-INV-00072',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00187',in:'INZ-INV-00071',am:4750.0,st:'Completed'},{qn:'INZ-QUO-00212',in:'INZ-INV-00070',am:5850.0,st:'Completed'},{qn:'INZ-QUO-00149',in:'INZ-INV-00069',am:253650.0,st:'Completed'},{qn:'INZ-QUO-00186',in:'INZ-INV-00068',am:10000.0,st:'Completed'},{qn:'INZ-QUO-00207',in:'INZ-INV-00067',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00132',in:'INZ-INV-00066',am:234996.4,st:'Completed'},{qn:'INZ-QUO-00204',in:'INZ-INV-00065',am:11250.0,st:'Completed'},{qn:'INZ-QUO-00167',in:'INZ-INV-00064',am:7500.0,st:'Completed'},{qn:'INZ-QUO-00142',in:'INZ-INV-00063',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00150',in:'INZ-INV-00062',am:233700.0,st:'Completed'},{qn:'INZ-QUO-00181',in:'INZ-INV-00061',am:800.0,st:'Completed'},{qn:'INZ-QUO-00191',in:'INZ-INV-00060',am:135558.0,st:'Completed'},{qn:'INZ-QUO-00143',in:'INZ-INV-00059',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00119',in:'INZ-INV-00058',am:260800.0,st:'Completed'},{qn:'INZ-QUO-00191',in:'INZ-INV-00057',am:8400.0,st:'Completed'},{qn:'INZ-QUO-00181',in:'INZ-INV-00056',am:75008.79,st:'Completed'},{qn:'INZ-QUO-00103',in:'INZ-INV-00055',am:800.0,st:'Completed'},{qn:'INZ-QUO-00132',in:'INZ-INV-00054',am:11250.0,st:'Completed'},{qn:'INZ-QUO-00181',in:'INZ-INV-00053',am:5175.0,st:'Completed'},{qn:'INZ-QUO-00127',in:'INZ-INV-00052',am:274788.0,st:'Completed'},{qn:'INZ-QUO-00030',in:'INZ-INV-00051',am:218500.0,st:'Completed'},{qn:'INZ-QUO-00103',in:'INZ-INV-00050',am:386000.0,st:'Completed'},{qn:'INZ-QUO-00149',in:'INZ-INV-00049',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00069',in:'INZ-INV-00048',am:8710.0,st:'Completed'},{qn:'INZ-QUO-00114',in:'INZ-INV-00047',am:13500.0,st:'Completed'},{qn:'INZ-QUO-00150',in:'INZ-INV-00046',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00111',in:'INZ-INV-00045',am:12500.0,st:'Completed'},{qn:'INZ-QUO-ZOCRAFT',in:'INZ-INV-00044',am:1768.2,st:'Completed'},{qn:'INZ-QUO-00074',in:'INZ-INV-00043',am:6000.0,st:'Completed'},{qn:'INZ-QUO-00127',in:'INZ-INV-00042',am:14175.0,st:'Completed'},{qn:'INZ-QUO-00075',in:'INZ-INV-00041',am:180730.0,st:'Completed'},{qn:'INZ-QUO-00069',in:'INZ-INV-00040',am:9600.0,st:'Completed'},{qn:'INZ-QUO-00087',in:'INZ-INV-00039',am:14500.0,st:'Completed'},{qn:'INZ-QUO-00119',in:'INZ-INV-00038',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00062',in:'INZ-INV-00037',am:62550.0,st:'Completed'},{qn:'INZ-QUO-00033',in:'INZ-INV-00036',am:166140.0,st:'Completed'},{qn:'INZ-QUO-00040',in:'INZ-INV-00035',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00125',in:'INZ-INV-00034',am:2000.0,st:'Completed'},{qn:'INZ-QUO-00103',in:'INZ-INV-00033',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00084',in:'INZ-INV-00032',am:72522.5,st:'Completed'},{qn:'INZ-QUO-00084',in:'INZ-INV-00031',am:6460.0,st:'Completed'},{qn:'INZ-QUO-00053',in:'INZ-INV-00030',am:15000.0,st:'Completed'},{qn:'INZ-QUO-00013',in:'INZ-INV-00018',am:196281.1,st:'Completed'},{qn:'INZ-QUO-00086',in:'INZ-INV-00029',am:4000.0,st:'Completed'},{qn:'INZ-QUO-00086',in:'INZ-INV-00028',am:2800.0,st:'Completed'},{qn:'INZ-QUO-00062',in:'INZ-INV-00027',am:5796.0,st:'Completed'},{qn:'INZ-QUO-00083',in:'INZ-INV-00026',am:2000.0,st:'Completed'},{qn:'INZ-QUO-00080',in:'INZ-INV-00025',am:800.0,st:'Completed'},{qn:'INZ-QUO-00039',in:'INZ-INV-00024',am:14255.0,st:'Completed'},{qn:'INZ-QUO-00077',in:'INZ-INV-00023',am:13000.0,st:'Completed'},{qn:'INZ-QUO-00009',in:'INZ-INV-00022',am:254000.0,st:'Completed'},{qn:'INZ-QUO-00075',in:'INZ-INV-00020',am:7600.0,st:'Completed'},{qn:'INZ-QUO-00026',in:'INZ-INV-00015',am:9500.0,st:'Completed'},{qn:'INZ-QUO-00033',in:'INZ-INV-00021',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00001',in:'INZ-INV-00007',am:165450.0,st:'Completed'},{qn:'INZ-QUO-00039',in:'INZ-INV-00019',am:330000.0,st:'Completed'},{qn:'INZ-QUO-00030',in:'INZ-INV-00017',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00031',in:'INZ-INV-00016',am:57735.0,st:'Completed'},{qn:'INZ-QUO-00008',in:'INZ-INV-00014',am:192900.0,st:'Completed'},{qn:'INZ-QUO-00016',in:'INZ-INV-00013',am:10544.0,st:'Completed'},{qn:'INZ-QUO-00016',in:'INZ-INV-00012',am:9432.0,st:'Completed'},{qn:'INZ-QUO-00013',in:'INZ-INV-00011',am:7600.0,st:'Completed'},{qn:'INZ-QUO-00015',in:'INZ-INV-00010',am:12500.0,st:'Completed'},{qn:'INZ-QUO-00014',in:'INZ-INV-00009',am:70520.0,st:'Completed'},{qn:'INZ-QUO-DP0069',in:'INZ-INV-00008',am:7650.0,st:'Completed'},{qn:'INZ-QUO-00009',in:'INZ-INV-00006',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00008',in:'INZ-INV-00005',am:8550.0,st:'Completed'},{qn:'INZ-QUO-00003',in:'INZ-INV-00003',am:11000.0,st:'Completed'},{qn:'INZ-QUO-00004',in:'INZ-INV-00004',am:700.0,st:'Completed'},{qn:'INZ-QUO-00002',in:'INZ-INV-00002',am:9000.0,st:'Completed'},{qn:'INZ-QUO-00001',in:'INZ-INV-00001',am:5640.0,st:'Completed'} ]; invs.forEach(v=>{ const q=findQ(v.qn);if(!q)return; if(!q.invoices)q.invoices=[]; if(q.invoices.some(x=>x.invNo===v.in))return; q.invoices.push({invNo:v.in,date:'',amount:v.am,status:v.st,createdAt:new Date().toISOString()}); chg=true; }); if(chg){ localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); QUOT_LIST.length=0;QUOT_LIST.push(..._ql); } localStorage.setItem('inzii_invoice_counter','95'); localStorage.setItem('inzii_mig_v4','1'); console.log('[INZII] Migration v4: q.invoiceโ†’q.invoices[] converted, all 95 invoices loaded.'); })(); // โ”€โ”€ End migration v4 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v5: import 13 quotations from PDF zip โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v5'))return; // [id, quotNo, revNum, client, phone, remarks, date, finalAmt, totalAmt, totalDisc] const pdfs=[ ['INZ-QUO-00278-R1','INZ-QUO-00278',1,'Sherry','+6016 779 8637','DP0191 - Sherry, Taman Pelangi','2025-12-11',15000,15000,0], ['INZ-QUO-00267-R0','INZ-QUO-00267',0,'Celine Lim','+6012 759 8838','DP0192 - Celine Lim, Sunway Lenang','2025-11-03',20000,20000,0], ['INZ-QUO-00301-R0','INZ-QUO-00301',0,'Chua Che Yen','+6016 499 3339','DP0208 - Chua Che Yen, Taman Ekoflora','2026-03-10',12000,12000,0], ['INZ-QUO-00204-R1','INZ-QUO-00204',1,'Jessy','+6019 728 6852','PJ1063 - Jessy, Forte Ekoflora','2026-01-21',1484000,1784800.65,300800.65], ['INZ-QUO-00264-R3','INZ-QUO-00264',3,'Koh Tiong Sim','+658914 5347','PJ1069 - Ms Chuang, Pulai','2025-11-05',687000,751910.5,64910.5], ['INZ-QUO-00279-R2','INZ-QUO-00279',2,'YJ','+6010 833 8382','PJ1077 - YJ, Eco Botanic','2025-12-11',258000,279068,21068], ['INZ-QUO-00287-R3','INZ-QUO-00287',3,'Lawrence Ong','+658912 1988','PJ1078 - Lawrence Ong, Senadi Hill','2026-06-15',255690,259800,4110], ['INZ-QUO-00306-R3','INZ-QUO-00306',3,'Sherry','+6016 779 8637','PJ1080 - Sherry, Taman Pelangi','2026-04-11',855000,874070.5,19070.5], ['INZ-QUO-00319-R0','INZ-QUO-00319',0,'Irene Chia Ai Ling','+6012 720 1655','DP0211 - Irene Chia Ai Ling, Setia Tropika','2026-05-13',21000,21000,0], ['INZ-QUO-00260-R0','INZ-QUO-00260',0,'Chang Jia Wen','+6012 313 0871','PJ1083 - Chang Jia Wen, PJ Old Town KL','2025-10-17',34626,34626,0], ['INZ-QUO-00313-R3','INZ-QUO-00313',3,'Dews Lim','+6012-746 5180','PJ1085 - Dews Lim, Eco Botanic','2026-04-27',252500,255626,3126], ['INZ-QUO-00285-R1','INZ-QUO-00285',1,'Pei Jia','+6017 881 7365','DP0198 - Chong Pei Jia, Taman EkoFlora','2026-04-28',12000,12000,0], ['INZ-QUO-00275-R0','INZ-QUO-00275',0,'Channale','+6012 782 1885','DP0195 - Channale, Austin Crest','2025-11-20',13500,13500,0], ]; const _fq=no=>QUOT_LIST.find(q=>q.id===no||q.id.replace(/-R\d+$/,'')===no||q.quotNo===no); pdfs.forEach(([id,quotNo,rev,client,phone,remarks,date,finalAmt,totalAmt,totalDisc])=>{ // skip if already exists (by exact id or base number) const existing=_fq(id)||_fq(quotNo); if(existing){ // update stub in-place if it has no real amount yet if(!existing.finalAmt||existing.finalAmt===0){ existing.client=client;existing.clientPhone=phone;existing.remarks=remarks; existing.date=date;existing.finalAmt=finalAmt;existing.totalAmt=totalAmt; existing.totalDisc=totalDisc;existing.revision=rev; existing.status='Won';existing.wonDeal=date; } return; } // create new entry const now=new Date().toISOString(); QUOT_LIST.push({ id,quotNo,revision:rev,client,clientPhone:phone,remarks, date,finalAmt,totalAmt,totalDisc,taxAmt:0, status:'Won',wonDeal:date, sections:[],pis:[],payments:[],invoices:[], createdAt:now,updatedAt:now }); }); // persist all localStorage.setItem('inzii_quotations',JSON.stringify(QUOT_LIST)); localStorage.setItem('inzii_mig_v5','1'); console.log('[INZII] Migration v5: 13 PDF quotations imported.'); })(); // โ”€โ”€ End migration v5 โ”€โ”€โ”€ // โ”€โ”€ Migration v6: Invoice dates โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function(){try{ if(localStorage.getItem('inzii_mig_inv_dates_v2'))return; const dates={'INZ-INV-00001':'2024-01-16','INZ-INV-00002':'2023-12-07','INZ-INV-00003':'2023-12-07','INZ-INV-00004':'2024-05-28','INZ-INV-00005':'2023-12-07','INZ-INV-00006':'2023-12-07','INZ-INV-00007':'2024-03-20','INZ-INV-00008':'2023-12-07','INZ-INV-00009':'2023-12-07','INZ-INV-00010':'2024-02-06','INZ-INV-00011':'2023-12-07','INZ-INV-00012':'2024-07-21','INZ-INV-00013':'2024-09-30','INZ-INV-00014':'2023-12-28','INZ-INV-00015':'2024-03-19','INZ-INV-00016':'2023-12-07','INZ-INV-00017':'2024-02-16','INZ-INV-00018':'2024-05-31','INZ-INV-00019':'2024-03-29','INZ-INV-00020':'2024-03-20','INZ-INV-00021':'2024-01-23','INZ-INV-00022':'2024-03-20','INZ-INV-00023':'2024-08-21','INZ-INV-00024':'2024-04-09','INZ-INV-00025':'2024-04-24','INZ-INV-00026':'2024-05-15','INZ-INV-00027':'2024-05-15','INZ-INV-00028':'2024-05-23','INZ-INV-00029':'2024-05-23','INZ-INV-00030':'2024-06-11','INZ-INV-00031':'2024-06-13','INZ-INV-00032':'2024-06-13','INZ-INV-00033':'2024-06-24','INZ-INV-00034':'2024-07-31','INZ-INV-00035':'2024-08-03','INZ-INV-00036':'2024-08-09','INZ-INV-00037':'2024-08-14','INZ-INV-00038':'2024-08-16','INZ-INV-00039':'2024-08-29','INZ-INV-00040':'2024-08-29','INZ-INV-00041':'2024-09-10','INZ-INV-00042':'2024-09-22','INZ-INV-00043':'2024-10-01','INZ-INV-00044':'2024-10-18','INZ-INV-00045':'2024-11-08','INZ-INV-00046':'2024-11-20','INZ-INV-00047':'2024-11-25','INZ-INV-00048':'2024-12-03','INZ-INV-00049':'2024-12-18','INZ-INV-00050':'2024-12-20','INZ-INV-00051':'2025-01-06','INZ-INV-00052':'2025-02-01','INZ-INV-00053':'2025-02-06','INZ-INV-00054':'2025-03-03','INZ-INV-00055':'2025-03-29','INZ-INV-00056':'2025-04-23','INZ-INV-00057':'2025-04-24','INZ-INV-00058':'2025-04-30','INZ-INV-00059':'2025-06-10','INZ-INV-00060':'2025-06-13','INZ-INV-00061':'2025-06-24','INZ-INV-00062':'2025-06-29','INZ-INV-00063':'2025-06-29','INZ-INV-00064':'2025-07-04','INZ-INV-00065':'2025-07-08','INZ-INV-00066':'2025-07-22','INZ-INV-00067':'2025-07-31','INZ-INV-00068':'2025-09-17','INZ-INV-00069':'2025-09-19','INZ-INV-00070':'2025-09-23','INZ-INV-00071':'2025-10-28','INZ-INV-00072':'2025-11-19','INZ-INV-00073':'2025-11-21','INZ-INV-00074':'2025-11-26','INZ-INV-00075':'2025-12-01','INZ-INV-00076':'2025-12-10','INZ-INV-00077':'2025-12-10','INZ-INV-00078':'2025-12-15','INZ-INV-00079':'2025-12-30','INZ-INV-00080':'2025-12-30','INZ-INV-00081':'2026-01-07','INZ-INV-00082':'2026-01-23','INZ-INV-00083':'2026-01-29','INZ-INV-00084':'2026-01-30','INZ-INV-00085':'2026-01-31','INZ-INV-00086':'2026-01-31','INZ-INV-00087':'2026-02-05','INZ-INV-00088':'2026-03-10','INZ-INV-00089':'2026-04-20','INZ-INV-00090':'2026-04-28','INZ-INV-00091':'2026-05-03','INZ-INV-00092':'2026-05-03','INZ-INV-00093':'2026-05-06','INZ-INV-00094':'2026-05-19','INZ-INV-00095':'2026-06-03'}; const ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); let chg=false; ql.forEach(q=>{(q.invoices||[]).forEach(inv=>{if(dates[inv.invNo]&&!inv.date){inv.date=dates[inv.invNo];chg=true;}});}); if(chg){ localStorage.setItem('inzii_quotations',JSON.stringify(ql)); // Also update in-memory QUOT_LIST so UI reflects dates immediately if(typeof QUOT_LIST!=='undefined'){ QUOT_LIST.forEach(q=>{(q.invoices||[]).forEach(inv=>{if(dates[inv.invNo]&&!inv.date)inv.date=dates[inv.invNo];});}); } } localStorage.setItem('inzii_mig_inv_dates_v2','1'); console.log('[INZII] Migration v6: Invoice dates updated.'); }catch(e){console.error('[INZII] Migration v6 error:',e);} })(); // โ”€โ”€ End migration v6 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v7: import INZ-QUO-00279-R2 (PJ1077 YJ Eco Botanic) โ”€โ”€ (function(){ const QID='INZ-QUO-00279-R2'; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); const _existing=_ql.find(q=>q.id===QID); if(_existing&&(_existing.sections||[]).length>0){return;} const u=()=>Math.random().toString(36).slice(2,10); const sec=(title,items)=>({id:u(),title,optional:false,items}); const it=(no,desc,desc2,qty,unit,rate)=>({type:'item',id:u(),no,desc,desc2,qty,unit,rate,cost:0,amount:qty*rate,foc:false,focRate:0}); const sh=(title)=>({type:'subhdr',id:u(),title}); const q={ id:QID,quotNo:'INZ-QUO-00279',revision:2, client:'YJ',clientPhone:'+6010 833 8382', date:'2025-12-11', remarks:'PJ1077 - YJ, Eco Botanic', handler:'Inzii Design', status:'Won',wonDeal:'2025-12-11',tag:'', finalAmt:258000,totalAmt:279068,totalDisc:21068,taxAmt:0, createdAt:'2025-12-11T00:00:00.000Z',updatedAt:'2025-12-11T00:00:00.000Z', paymentTerm:'Design and Renovation (40%, 30%, 20%, 10%)', termCondition:'Terms & Conditions - Construction', sections:[ sec('Masonry Work',[ sh('To Provide Demolition and Hacking Work'), it(1,'To Supply Labour to Demolish Existing Tiles Skirting and Skim Wall to Receive New SPC Flooring and Skirting at Entire House','',1,'JOB',3200), it(2,'To Demolish Existing Floor Tiles at Ground Floor','',1,'JOB',5300), it(3,'To Demolish and Modify Existing Staircase Step','',1,'JOB',3400), it(4,'To Demolish Existing Staircase Tiles c/w Patch Plaster Work','',1,'JOB',0), it(5,'To Demolish Existing Staircase Handrail','',1,'JOB',0), it(6,'To Demolish Existing Door at Store and Bathroom 1','',1,'JOB',0), it(7,'To Dismantle Existing Toilet Bowl, Basin and Shower Mixer at Bathroom 1','',1,'JOB',0), it(8,'To Demolish Existing Wall Tiles and Floor Tiles at Bathroom 1','Dimension : Wall Tiles - W7530 H3100\nDimension : Floor Tiles - 40sqft',1,'JOB',1900), it(9,'To Demolish Existing Wall Tiles c/w Patch Plaster Work at Wet Kitchen','Dimension : W320+700+980+3400 H1800',1,'JOB',2000), it(10,'To Demolish Existing Wall, Door and Door Frame at Master Bedroom','Dimension : W1500 H2100',1,'JOB',550), it(11,'To Demolish Existing Wall Tiles and Floor Tiles at Master Bathroom','Dimension : Wall Tiles - W8390 H3000\nDimension : Floor Tiles - 46sqft',1,'JOB',2200), it(12,'To Dismantle Existing Basin, Toilet Bowl and Shower Mixer at Master Bathroom','',1,'JOB',0), sh('To Provide Minor Concrete, Erect Brick Wall and Plaster Work'), it(13,'To Core a Round Hole for Cooker Hood Ducting at Wet Kitchen','',1,'JOB',350), it(14,'To Construct New Brick Wall and Lintel to Receive New Door at Master Bedroom','Overall Dimension : W1500 H2100',1,'JOB',1600), ]), sec('Tiles Work',[ sh('Living'), it(15,'To Supply Labour to Lay New 600x1200mm Floor Tiles and Wall Tiles (*Not Including Tiles)','Dimension : 750sqft',1,'JOB',12000), sh('Bathroom 1'), it(16,'To Supply Labour to Lay New 600x600mm Floor Tiles and Wall Tiles and New 150x150mm Wall Tiles (*Not Including Tiles)','- c/w 3 Layers QuicSeal 104 Waterproofing\n- c/w 1800mmH for Shower Area Walls, 300mmH for Remaining Walls\nDimension : Wall Tiles - W260+900+1715+1790+1975 H3000, W890 H3000\nDimension : Floor Tiles - 40sqft',1,'JOB',7700), sh('Master Bathroom'), it(17,'To Supply Labour to Lay New 600x600mm Floor Tiles and Wall Tiles and New 150x150mm Wall Tiles (*Not Including Tiles)','- c/w 3 Layers QuicSeal 104 Waterproofing\n- c/w 1800mmH for Shower Area Walls, 300mmH for Remaining Walls\nDimension : Wall Tiles - W905+260 H2800, W1475+1735+2590 H2700, W1685 H2800\nDimension : Floor Tiles - 46sqft',1,'JOB',7900), ]), sec('Plumbing Work',[ it(18,'To Supply and Install New PPR Hot and Cold Water Piping for Shower Mixed and Wash Basin at Bathroom 1','',1,'JOB',2200), it(19,'To Supply Labour and Install New Toilet Bowl at Bathroom 1','',1,'JOB',350), it(20,'To Supply and Install Inlet and Outlet Water Piping for Sink at Dry Kitchen','',1,'JOB',800), it(21,'To Supply and Install Inlet and Outlet Water Piping for Robot Vacuum at Wet Kitchen','',1,'JOB',700), it(22,'To Supply and Install Inlet and Outlet Water Piping for Washer at Wet Kitchen','',1,'JOB',700), it(23,'To Supply and Install Inlet and Outlet Water Piping for Sink at Wet Kitchen','',1,'JOB',800), it(24,'To Supply and Install Inlet and Outlet Water Piping for Tap at Backyard','',1,'JOB',350), it(25,'To Supply and Install New PPR Hot and Cold Water Piping for Shower Mixed and Wash Basin at Master Bathroom','',1,'JOB',2200), it(26,'To Supply Labour and Install New Toilet Bowl at Master Bathroom','',1,'JOB',350), it(27,'To Supply Labour and Install New Basin at Bathroom 1 and Bathroom 2','',2,'JOB',350), ]), sec('M&E Work',[ it(28,'Lighting Point (Eyeball, Hanging Light, Surface)','',78,'NOS',90), it(29,'Staircase Light Point','',6,'NOS',110), it(30,'Magnetic Track Light Point','',1,'NOS',95), it(31,'Wall Light Point','',9,'NOS',90), it(32,'TV Point','',1,'NOS',130), it(33,'Data Point','',1,'NOS',300), it(34,'Network Point','',1,'NOS',300), it(35,'CCTV Point','',1,'NOS',120), it(36,'13 Amp Power Socket Point','',30,'NOS',120), it(37,'Waterproof 13 Amp Power Point','',1,'NOS',130), it(38,'15 Amp Power Socket Point','',3,'NOS',250), it(39,'Ceiling Fan Point','',5,'NOS',90), it(40,'Exhaust Fan Point','',4,'NOS',90), it(41,'Neutral Point','',1,'JOB',250), it(42,'Relocate Door Bell','',1,'NOS',80), it(43,'Relocate Power Point','',5,'NOS',65), it(44,'Change Switch Socket','',1,'JOB',550), it(45,'Light Install','',62,'NOS',15), it(46,'Awning Light Install','',6,'NOS',20), it(47,'Wall Light Install','',9,'NOS',30), it(48,'Magnetic Track Light Install','',1,'NOS',130), it(49,'Pendant Light / Hanging Light Install','',1,'NOS',200), it(50,'Outdoor Pillar Light Install','',1,'NOS',30), it(51,'LED Light Install','',50,'M',20), it(52,'Arcylic LED Point','',2,'NOS',110), it(53,'Ceiling Fan Install','',5,'NOS',90), it(54,'Exhaust Fan Install','',4,'NOS',40), it(55,'Heater Install','',3,'NOS',130), it(56,'CCTV Install','',2,'NOS',65), it(57,'Conceal PVC Pipe','',1,'JOB',1500), ]), sec('Air Conditioning Piping Work',[ it(58,'To Supply Labour to Dismantle and Re-arrange A/C Complete with All Necessary Construction at Living Area','',1,'JOB',750), it(59,'To Supply Labour to Dismantle and Re-arrange A/C Complete with All Necessary Construction at Master Bedroom','',1,'JOB',1250), ]), sec('Plaster Ceiling & Partition Work',[ sh('Ground Floor'), it(60,'Plain Plaster Ceiling','',750,'SQFT',5), it(61,'Double Sided Partition at Staircase','',1,'JOB',3100), it(62,'Double Sided Partition at Wet Kitchen','',1,'JOB',650), it(63,'Manhole 18"','',2,'NOS',110), it(64,'Plaster Ceiling L Box','',54,'FT',22), it(65,'Plaster Ceiling Light Holder','',15,'FT',23), it(66,'Fan Hook','',2,'NOS',65), it(67,'H Profile Install','',1,'JOB',1200), it(68,'Add Wood Support','',1,'JOB',65), it(69,'Ceramic Lamp','',30,'NOS',120), it(70,'Magnetic Track Light c/w Hole Drilling','',1,'JOB',750), sh('First Floor'), it(71,'Plain Plaster Ceiling','',342,'SQFT',5), it(72,'Double Sided Partition at Master Bedroom','',1,'JOB',2600), it(73,'Plaster Ceiling L Box','',37,'FT',22), it(74,'Plaster Ceiling Light Holder','',17,'FT',23), it(75,'Fan Hook','',3,'NOS',65), ]), sec('Aluminium and Glass Work',[ sh('Ground Floor โ€” Bathroom 1'), it(76,'Shower Screen Fixed Panel c/w 10mm Tempered Clear Glass with Concealed MF "U" Channel','Dimension : W640 H2100',1,'SET',750), sh('Ground Floor โ€” Wet Kitchen'), it(77,'Sliding Door c/w 6mm Tempered Frosted Glass and Slim Line Aluminium Frame in p/c Black Finish','Dimension : W1000 H2800\n- c/w Metal Support',1,'SET',4500), sh('First Floor โ€” Master Bathroom'), it(78,'Aluminium Basin c/w Full ACP Body and 4G Door Frame','Dimension : W800 D500 H500\nDimension : Quartz Table Top - W800 D500',1,'SET',2000), it(79,'Shower Screen Fixed Panel c/w 10mm Tempered Clear Glass and 4 Sides Aluminium Frame in p/c Black Finish','Dimension : W775 H2100',1,'SET',1000), ]), sec('Flooring Work (SPC, Vinyl and Laminate)',[ it(80,'To Supply and Install 5mm SPC Click System Flooring including Necessary Skirting, Beading and L Profile at First Floor','',1,'JOB',9200), it(81,'To Supply and Install 5mm SPC Click System Flooring including Necessary Skirting, Beading and L Profile at Staircase Area','',1,'JOB',4700), ]), sec('Decking Work',[ sh('Backyard'), it(82,'To Supply and Install WPC Deck Board onto 25mm H Aluminium Batten with Accessories','Dimension : 5945mm x 1360mm',1,'JOB',5500), ]), sec('Awning & Metal Work',[ sh('Car Porch'), it(83,'Aluminium Awning with Deco Panel Ceiling','Dimension : 6245mm x 1500mm',1,'JOB',6200), sh('Backyard'), it(84,'Aluminium Awning with Deco Panel Ceiling c/w Gutter','Dimension : 6245mm x 1500mm',1,'JOB',9500), sh('Staircase'), it(85,'Metal Staircase Handle','Dimension : W7000 H10',1,'JOB',2400), ]), sec('Painting & Touch Up Work',[ it(86,'To Supply Labour and Material','- To Clean Off Existing Exterior Wall Stain with Water Jet for Exterior Stain\n- To Touch Up Crack Line Area and Holes Area After Cleaning Work\n- To Lay Oil Sealer for Exterior Wall and Fencing\n- To Construct Painting Work for :\n a) Exterior Wall - Jotun Ultra Clean Series (Follow Management)\n b) Interior Wall - Jotun Majestic Series / Nippon Easywash Series (3 Color)\n c) Door, Door Frame - Included (1 Color)\n d) Ceiling - Included (1 Color)\n e) Staircase Railing - Included (1 Color)',1,'JOB',12000), ]), sec('Carpentry Work',[ sh('Ground Floor โ€” Foyer'), it(87,'Shoe Cabinet c/w Solid Plywood In Selected Laminated Finish','Dimension : Shoe Cabinet - W1800 D350 H1000\nDimension : Stone Design - W200 H1000',1,'SET',4600), sh('Ground Floor โ€” Living'), it(88,'Altar c/w Solid Plywood In Selected Laminated Finish','Dimension : Altar c/w Round Metal Design - W1800 D520 H375',1,'SET',4600), it(89,'Display Cabinet c/w Solid Plywood In Selected Laminated Finish','Dimension : Display Cabinet - W1230 D4000 H2700\nDimension : Acrylic Light Panel - W850 H1200\nDimension : Acrylic Shelving - W850 D350 H1200',1,'SET',6900), sh('Ground Floor โ€” Staircase'), it(90,'Platform, Carpentry Boxed Up and TV Console c/w Solid Plywood In Selected Laminated Finish','Dimension : Platform - W4640 D2060 H200\nDimension : Carpentry Boxed Up - W200 H750\nDimension : TV Console - W4640 D675 H200',1,'SET',7900), sh('Ground Floor โ€” Dry Kitchen'), it(91,'Top Cabinet and Hanging Cabinet c/w Solid Plywood In Selected Laminated Finish','Dimension : Top Cabinet - W2650 D350 H800\nDimension : Hanging Cabinet c/w Handle - W3300 D600 H650\nDimension : Stainless Steel Table Top and Backsplash - W3300 D600 H250',1,'SET',17600), sh('Ground Floor โ€” Wet Kitchen'), it(92,'Stainless Steel Shelving and Base Cabinet c/w Solid Plywood In Selected Laminated Finish','Dimension : Stainless Steel Shelving - W2300 D200\nDimension : Base Cabinet - W3280 D600 H850\nDimension : Sintered Stone Table Top with Skirting (+Sink Hole) - W3280 D600 H100',1,'SET',9400), it(93,'Tall Cabinet, Top Cabinet and Base Cabinet c/w Solid Plywood In Selected Laminated Finish','Dimension : Tall Cabinet - W900 D600 H2800\nDimension : Top Cabinet - W1980 D350 H1300\nDimension : Base Cabinet - W1980 D600 H850\nDimension : Sintered Stone Table Top (+Cooker Hood) - W1980 D600\nDimension : Sintered Stone Backsplash - W1980 H650\n- Including Kitchen Basket Under Stove',1,'SET',16300), sh('First Floor โ€” Master Bedroom'), it(94,'Bedhead and Bedside Drawer c/w Solid Plywood In Selected Laminated Finish','Dimension : Bedhead - W3160 H2400\nDimension : Bedside Drawer - W500+750 D450 H150',1,'SET',9100), it(95,'Openshelf, Dressing Table with Feature Wall c/w Solid Plywood In Selected Laminated Finish','Dimension : Openshelf with Sliding Mirror c/w Accessory - W625 D630 H2700\nDimension : Dressing Table with Feature Wall - W1580 D630 H200, W500 H1000',1,'SET',8800), it(96,'Wardrobe and Display Box c/w Solid Plywood In Selected Laminated Finish','Dimension : Open Wardrobe with Metal Hanging Rod - W1100 D600 H3000\nDimension : Wardrobe - W2250+800 D600 H3000\nDimension : Display Box - W385 D325 H700',1,'SET',16500), sh('First Floor โ€” Master Bathroom'), it(97,'Feature Wall c/w Solid Plywood In Selected Laminated Finish','Dimension : Feature Wall c/w Mirror - W1670 H940',1,'SET',1400), it(98,'To Supply and Install 15mm Quartz Stone at Shower Niche','Dimension : 290mm x 280mm',1,'SET',100), sh('First Floor โ€” Bedroom 3'), it(99,'Wardrobe c/w Solid Plywood In Selected Laminated Finish','Dimension : Wardrobe - W1800 D600 H3000',1,'SET',8000), sh('Overall'), it(100,'Cabinet Edging Touch Up','',1,'JOB',3500), ]), sec('Miscellaneous Work',[ it(101,'To Supply 4 Waste Bins to Clear Debris During Renovation Period','*Remarks : If the limit is exceeded, additional waste bins charges will be applied.',1,'JOB',1200), it(102,'To Supply and Lay Floorgard Mat Floor Protection 1 Times During Renovation Period','*Remarks : If the limit is exceeded, additional cleaning charges will be applied.',1,'JOB',2000), it(103,'To Supply Labour and Material to Clean The Entire Unit 2 Times (in the middle and the end of renovation period)','*Remarks : If the limit is exceeded, additional cleaning charges will be applied.',1,'JOB',2000), ]), ] }; if(_existing){ // Stub exists from v5 โ€” inject sections Object.assign(_existing,q); } else { _ql.push(q); } // Also update in-memory QUOT_LIST const _mi=QUOT_LIST.findIndex(qq=>qq.id===QID); if(_mi>=0){Object.assign(QUOT_LIST[_mi],q);}else{QUOT_LIST.push(q);} localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); console.log('[INZII] Migration v7: INZ-QUO-00279-R2 imported.'); })(); // โ”€โ”€ End migration v7 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v8: import INZ-QUO-00204-R1 โ”€โ”€ (function(){ const QID='INZ-QUO-00204-R1'; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); const _ex=_ql.find(q=>q.id===QID); if(_ex&&(_ex.sections||[]).length>0){return;} const q={"id": "INZ-QUO-00204-R1", "quotNo": "INZ-QUO-00204", "revision": 1, "client": "Jessy", "clientPhone": "+6019 728 6852", "remarks": "PJ1063 - Jessy, Forte Ekoflora", "date": "2026-01-21", "finalAmt": 1484000, "totalAmt": 1784800.65, "totalDisc": 300800.65, "taxAmt": 0, "handler": "Wei Ni", "status": "Won", "wonDeal": "2026-01-21", "paymentTerm": "Design and Renovation (40%, 30%, 20%, 10%)", "termCondition": "Terms & Conditions - Construction Use", "designAgreement": "", "address": "25, Jalan Ekoflora 2/6, Taman Ekoflora, 81100 Johor Bahru, Johor.", "sections": [{"id": "qt204r1_s0", "title": "Masonry Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s0_0", "no": "1", "desc": "To Supply Labour to Demolish Existing Tiles Skirting and Skim Wall to Receive New SPC Flooring and Skirting at Staircase Area and First Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1950, "cost": 0, "amount": 1950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_1", "no": "2", "desc": "To Demolish Existing Floor Tiles to Receive New Floor Tiles at Ground Floor Entrance, Living and Dining", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4400, "cost": 0, "amount": 4400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_2", "no": "3", "desc": "To Construct Single Storey Extension for New Entertainment Room, Study Room and Kitchen c/w Waterproofing\nDimension : 14023mm x 3740mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 48800, "cost": 0, "amount": 48800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_3", "no": "4", "desc": "To Construct New Concrete Slab to Receive New Floor Tiles at Car Porch\nDimension : 7047mm x 2240mm (175sqft)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4500, "cost": 0, "amount": 4500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_4", "no": "5", "desc": "To Construct New Concrete Floor Slab to Receive New Floor Tiles at Terrace\nDimension : 3000mm x 15677mm (523sqft)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 29300, "cost": 0, "amount": 29300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_5", "no": "6", "desc": "To Construct New Brick Wall Fencing\nDimension : W8780 H1800", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4800, "cost": 0, "amount": 4800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_6", "no": "7", "desc": "To Conceal Downpipe Outlet for Planter Box", "desc2": "", "qty": 7, "unit": "NOS", "rate": 450, "cost": 0, "amount": 3150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_7", "no": "8", "desc": "To Demolish Existing Wall at Foyer and Staircase c/w Patch Plaster Work\nDimension : W1700 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1600, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_8", "no": "9", "desc": "To Demolish Existing Wall and Door at Entrance and Staircase\nOverall Dimension : W3130 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_9", "no": "10", "desc": "To Construct New RC Staircase", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1350, "cost": 0, "amount": 1350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_10", "no": "11", "desc": "To Demolish Existing Wall, Door and Window at Living and Dining", "desc2": "", "qty": 1, "unit": "JOB", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_11", "no": "12", "desc": "To Construct New Brick Wall and Lintel to Receive New Fixed Glass Window\nDimension : W3000 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2950, "cost": 0, "amount": 2950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_12", "no": "13", "desc": "To Construct New Brick Wall and Lintel to Receive New Sliding Glass Door", "desc2": "", "qty": 1, "unit": "JOB", "rate": 11950, "cost": 0, "amount": 11950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_13", "no": "14", "desc": "To Construct New Concrete Floor Slab and Raise Floor Level To 150HT From Existing Living Level to Receive New SPC Flooring\nDimension : 3665mm x 8780mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 20000, "cost": 0, "amount": 20000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_14", "no": "15", "desc": "To Demolish Existing Wall at Maid Room\nDimension : W2850 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_15", "no": "16", "desc": "To Construct New Brick Wall and Lintel to Receive New Pivot Door at Maid Room\nDimension : Brick Wall - W2095 H3000, W950 H3000 / Pivot Door - W900 H2100", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3900, "cost": 0, "amount": 3900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_16", "no": "17", "desc": "To Construct New Brick Wall and Lintel to Receive New Folding Door at Maid Room\nDimension : Brick Wall - W700 H3000 / Folding Door - W800 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1500, "cost": 0, "amount": 1500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_17", "no": "18", "desc": "To Demolish Existing Wall to Receive New Top Hung Window c/w Patch Plaster Work at Maid Room\nDimension : W600 H600", "desc2": "", "qty": 1, "unit": "JOB", "rate": 850, "cost": 0, "amount": 850, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_18", "no": "19", "desc": "To Lower Down Existing Floor Level from Maid Room and Demolish Existing Floor Tiles to Receive New Bathroom\nDimension : 800mm x 1500mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 300, "cost": 0, "amount": 300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_19", "no": "20", "desc": "To Demolish Existing Wall and Window at Kitchen\nOverall Dimension : W4055 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_20", "no": "21", "desc": "To Construct New Brick Wall and Lintel to Receive New Window at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 7500, "cost": 0, "amount": 7500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_21", "no": "22", "desc": "To Construct New Concrete Floor Slab to Receive New Floor Tiles at Kitchen\nDimension : Kitchen - 3590mm x 4710mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 10000, "cost": 0, "amount": 10000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_22", "no": "23", "desc": "To Core a Round Hole for Cooker Hood Ducting", "desc2": "", "qty": 1, "unit": "JOB", "rate": 450, "cost": 0, "amount": 450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_23", "no": "24", "desc": "To Construct New Brick Wall and Lintel to Receive New Pivot Door and Window at Laundry", "desc2": "", "qty": 1, "unit": "JOB", "rate": 6900, "cost": 0, "amount": 6900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_24", "no": "25", "desc": "To Construct New Concrete Floor Slab to Receive New Floor Tiles at Laundry (*Not Including Floor Tiles)\nDimension : 1658mm x 3290mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4500, "cost": 0, "amount": 4500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_25", "no": "26", "desc": "To Demolish Existing Brick Wall at Master Bathroom", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1600, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_26", "no": "27", "desc": "To Demolish Existing Door and Construct New Brick Wall at Master Bathroom\nDimension : W927 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1150, "cost": 0, "amount": 1150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_27", "no": "28", "desc": "To Demolish Existing Timber Floor to Receive New Floor Tiles at Master Bathroom\nDimension : 2885mm x 3690mm, 3462mm x 1738mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 550, "cost": 0, "amount": 550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_28", "no": "29", "desc": "To Conceal U Channel to Receive New Fixed Glass at Master Bathroom\nDimension : W750", "desc2": "", "qty": 1, "unit": "JOB", "rate": 600, "cost": 0, "amount": 600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_29", "no": "30", "desc": "To Construct New Wall Niches at Master Bathroom\nDimension : 700mm x 150mm H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1000, "cost": 0, "amount": 1000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_30", "no": "31", "desc": "To Construct New Brick Wall and Lintel to Receive New Sliding Door at Master Bathroom\nDimension : Brick Wall - W938 H3000 / Sliding Door - W800 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1950, "cost": 0, "amount": 1950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s0_31", "no": "32", "desc": "To Demolish Existing Wall and Conceal U Channel to Receive New Fixed Glass at Master Bathroom\nDimension : W867 H3000", "desc2": "", "qty": 1, "unit": "JOB", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s1", "title": "Tiles Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s1_0", "no": "33", "desc": "To Supply Labour to Lay New 300mmx600mm Floor Tiles at Car Porch (*Not Including Tiles)\nDimension : 175sqft", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3960, "cost": 0, "amount": 3960, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_1", "no": "34", "desc": "To Supply Labour to Lay New 600mmx1200mm Floor Tiles at Terrace (*Not Including Tiles)\nDimension : 3000mm x 15677mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 13520, "cost": 0, "amount": 13520, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_2", "no": "35", "desc": "To Supply Labour to Lay New 750mmx1500mm Floor Tiles at Ground Floor Entrance, Living, Dining and Bedroom 4 (*Not Including Tiles)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 32470, "cost": 0, "amount": 32470, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_3", "no": "36", "desc": "To Supply Labour to Lay New 300mmx600mm Floor Tiles and Wall Tiles at Bathroom 5 (*Not Including Tiles)\nc/w 2 Layers Pentens T-305 Waterproofing for Wall (1800mmHT)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4900, "cost": 0, "amount": 4900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_4", "no": "37", "desc": "To Supply Labour to Lay New 300mmx300mm Floor Tiles at Wet Kitchen (*Not Including Tiles)\nDimension : Wet Kitchen - 4345mm x 5240mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4900, "cost": 0, "amount": 4900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_5", "no": "38", "desc": "To Supply Labour to Lay New 600mmx1200mm Wall Tiles at Kitchen (*Not Including Tiles)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 14400, "cost": 0, "amount": 14400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_6", "no": "39", "desc": "To Supply Labour to Lay New 600mmx1200mm Floor Tiles at Laundry (*Not Including Tiles)\nDimension : 1658mm x 7040mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4700, "cost": 0, "amount": 4700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_7", "no": "40", "desc": "To Supply Labour to Lay New 600mmx1200mm Floor Tiles and Wall Tiles at Master Bathroom (*Not Including Tiles)\nc/w 2 Layers Pentens T-305 Waterproofing for Wall (1800mmHT)\nc/w 3 Layers Pentens T-305 Waterproofing for Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 18750, "cost": 0, "amount": 18750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s1_8", "no": "41", "desc": "To Supply and Install 16\" x 16\" Manhole at Ground Floor", "desc2": "", "qty": 4, "unit": "JOB", "rate": 470, "cost": 0, "amount": 1880, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s2", "title": "Plumbing Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s2_0", "no": "42", "desc": "To Supply and Install Inlet and Outlet Water Piping for Sink at Dry Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_1", "no": "43", "desc": "To Supply and Install Inlet and Outlet Water Piping for Sink at Wet Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_2", "no": "44", "desc": "To Supply and Install Inlet and Outlet Water Piping for Dish Washer at Wet Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 590, "cost": 0, "amount": 590, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_3", "no": "45", "desc": "To Supply and Install Inlet and Outlet Water Piping for Robot Vacuum at Wet Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_4", "no": "46", "desc": "To Supply and Install Inlet and Outlet Water Piping for Sink at Laundry", "desc2": "", "qty": 1, "unit": "JOB", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_5", "no": "47", "desc": "To Supply and Install Inlet and Outlet Water Piping for Washing Machine at Laundry", "desc2": "", "qty": 1, "unit": "JOB", "rate": 760, "cost": 0, "amount": 760, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_6", "no": "48", "desc": "To Supply and Install Inlet and Outlet Water Piping for Toilet Bowl and Shower Cap at Bathroom 5", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3550, "cost": 0, "amount": 3550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_7", "no": "49", "desc": "To Supply and Install Inlet and Outlet Water Piping for Water Tap at Terrace", "desc2": "", "qty": 2, "unit": "JOB", "rate": 800, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_8", "no": "50", "desc": "To Supply and Install Inlet Water Piping for Pond at Terrace", "desc2": "", "qty": 1, "unit": "JOB", "rate": 350, "cost": 0, "amount": 350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_9", "no": "51", "desc": "To Supply and Install PPR Hot and Cold Inlet and Outlet Water Piping for Basin, Bathtub and Shower Cap; Normal Inlet and Outlet Piping for Toilet Bowl at Master Bathroom", "desc2": "", "qty": 1, "unit": "JOB", "rate": 6950, "cost": 0, "amount": 6950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s2_10", "no": "52", "desc": "To Supply and Install Inlet and Outlet Water Piping for Washing Machine at Master Bathroom", "desc2": "", "qty": 1, "unit": "JOB", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s3", "title": "M&E Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s3_0", "no": "53", "desc": "Eyeball/Downlight/Surface Lighting Point", "desc2": "", "qty": 120, "unit": "NOS", "rate": 100, "cost": 0, "amount": 12000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_1", "no": "54", "desc": "LED Light Point", "desc2": "", "qty": 80, "unit": "NOS", "rate": 60, "cost": 0, "amount": 4800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_2", "no": "55", "desc": "Wall Light Point", "desc2": "", "qty": 21, "unit": "NOS", "rate": 150, "cost": 0, "amount": 3150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_3", "no": "56", "desc": "13 Amp Power Socket Point", "desc2": "", "qty": 59, "unit": "NOS", "rate": 170, "cost": 0, "amount": 10030, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_4", "no": "57", "desc": "20Amp Power Point (2.5mm)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 350, "cost": 0, "amount": 700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_5", "no": "58", "desc": "2 Way Switch/2 Way Light Point", "desc2": "", "qty": 6, "unit": "NOS", "rate": 210, "cost": 0, "amount": 1260, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_6", "no": "59", "desc": "Fan Point", "desc2": "", "qty": 9, "unit": "NOS", "rate": 110, "cost": 0, "amount": 990, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_7", "no": "60", "desc": "Hood Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 230, "cost": 0, "amount": 230, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_8", "no": "61", "desc": "Hob Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 230, "cost": 0, "amount": 230, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_9", "no": "62", "desc": "Oven Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 350, "cost": 0, "amount": 350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_10", "no": "63", "desc": "Air Cond Power Point", "desc2": "", "qty": 2, "unit": "NOS", "rate": 350, "cost": 0, "amount": 700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_11", "no": "64", "desc": "Water Heater Point", "desc2": "", "qty": 2, "unit": "NOS", "rate": 350, "cost": 0, "amount": 700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_12", "no": "65", "desc": "Exhaust Fan Point", "desc2": "", "qty": 4, "unit": "NOS", "rate": 110, "cost": 0, "amount": 440, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_13", "no": "66", "desc": "Exhaust Fan Install", "desc2": "", "qty": 4, "unit": "NOS", "rate": 40, "cost": 0, "amount": 160, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_14", "no": "67", "desc": "Light Install", "desc2": "", "qty": 109, "unit": "NOS", "rate": 20, "cost": 0, "amount": 2180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_15", "no": "68", "desc": "Led Casing Install", "desc2": "", "qty": 21, "unit": "SET", "rate": 80, "cost": 0, "amount": 1680, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_16", "no": "69", "desc": "Pendant Light / Hanging Light Install", "desc2": "", "qty": 3, "unit": "NOS", "rate": 55, "cost": 0, "amount": 165, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_17", "no": "70", "desc": "Magnetic Track Light Install", "desc2": "", "qty": 3, "unit": "NOS", "rate": 55, "cost": 0, "amount": 165, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_18", "no": "71", "desc": "Fan Install", "desc2": "", "qty": 9, "unit": "NOS", "rate": 80, "cost": 0, "amount": 720, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_19", "no": "72", "desc": "Water Heater Install", "desc2": "", "qty": 2, "unit": "NOS", "rate": 170, "cost": 0, "amount": 340, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_20", "no": "73", "desc": "Move Heater Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 160, "cost": 0, "amount": 160, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_21", "no": "74", "desc": "Move TV Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 110, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_22", "no": "75", "desc": "Move Data Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 150, "cost": 0, "amount": 150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_23", "no": "76", "desc": "Move Tel Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 110, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_24", "no": "77", "desc": "Change Switch Socket", "desc2": "", "qty": 50, "unit": "NOS", "rate": 20, "cost": 0, "amount": 1000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_25", "no": "78", "desc": "Outdoor Timer Point", "desc2": "", "qty": 3, "unit": "NOS", "rate": 470, "cost": 0, "amount": 1410, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_26", "no": "79", "desc": "Outdoor Power Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 510, "cost": 0, "amount": 510, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_27", "no": "80", "desc": "Outdoor Lighting Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 270, "cost": 0, "amount": 270, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s3_28", "no": "81", "desc": "Outdoor Isolator Point (EV Charger)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 3200, "cost": 0, "amount": 3200, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s4", "title": "Air Conditioning Piping Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s4_0", "no": "82", "desc": "To Supply and Install New 2.0hp AC Copper Refrigerant Piping at Entertainment Room", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3710, "cost": 0, "amount": 3710, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s4_1", "no": "83", "desc": "To Supply and Modify Existing AC Copper Refrigerant Piping at Walk-in Wardrobe Area", "desc2": "", "qty": 1, "unit": "JOB", "rate": 510, "cost": 0, "amount": 510, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s4_2", "no": "84", "desc": "To Supply and Modify Existing AC Copper Refrigerant Piping at Ground Floor and Living Area", "desc2": "", "qty": 2, "unit": "JOB", "rate": 800, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s4_3", "no": "85", "desc": "To Supply Labour and Conceal Water Pipe", "desc2": "", "qty": 4, "unit": "JOB", "rate": 200, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s4_4", "no": "86", "desc": "To Supply Labour and Fitting to Install 1.0-1.5hp Wall-mounted AC at Corridor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 470, "cost": 0, "amount": 470, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s4_5", "no": "87", "desc": "To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Bedroom 2, Bedroom 3, Bedroom 4, Master Bedroom and Walk-in Wardrobe", "desc2": "", "qty": 5, "unit": "JOB", "rate": 600, "cost": 0, "amount": 3000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s4_6", "no": "88", "desc": "To Supply Labour and Fitting to Install 2.0-3.0hp Cassette AC at Living and Entertainment Area", "desc2": "", "qty": 2, "unit": "JOB", "rate": 730, "cost": 0, "amount": 1460, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s5", "title": "Plaster Ceiling & Partition Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s5_0", "no": "89", "desc": "Dismantle Existing Ceiling (Ground Floor)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2580, "cost": 0, "amount": 2580, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_1", "no": "90", "desc": "Plain Plaster Ceiling (Ground Floor)", "desc2": "", "qty": 1263, "unit": "SQFT", "rate": 5.2, "cost": 0, "amount": 6567.6, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_2", "no": "91", "desc": "Plaster Ceiling Light Holder (Ground Floor)", "desc2": "", "qty": 87, "unit": "FT", "rate": 24, "cost": 0, "amount": 2088, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_3", "no": "92", "desc": "Plaster Ceiling L Box (Ground Floor)", "desc2": "", "qty": 16, "unit": "FT", "rate": 22, "cost": 0, "amount": 352, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_4", "no": "93", "desc": "Conceal Magnetic Track", "desc2": "", "qty": 1, "unit": "SET", "rate": 1070, "cost": 0, "amount": 1070, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_5", "no": "94", "desc": "Fan Hook", "desc2": "", "qty": 4, "unit": "NOS", "rate": 70, "cost": 0, "amount": 280, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_6", "no": "95", "desc": "A/C Cassette", "desc2": "", "qty": 2, "unit": "NOS", "rate": 70, "cost": 0, "amount": 140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_7", "no": "96", "desc": "Manhole 18\"", "desc2": "", "qty": 5, "unit": "NOS", "rate": 125, "cost": 0, "amount": 625, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_8", "no": "97", "desc": "Pendant Light Support", "desc2": "", "qty": 2, "unit": "NOS", "rate": 70, "cost": 0, "amount": 140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_9", "no": "98", "desc": "Conceal Eye Ball", "desc2": "", "qty": 18, "unit": "NOS", "rate": 125, "cost": 0, "amount": 2250, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_10", "no": "99", "desc": "Dismantle Existing Ceiling (First Floor)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4140, "cost": 0, "amount": 4140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_11", "no": "100", "desc": "Plain Plaster Ceiling (First Floor)", "desc2": "", "qty": 1006, "unit": "SQFT", "rate": 5.2, "cost": 0, "amount": 5231.2, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_12", "no": "101", "desc": "Plaster Ceiling Light Holder (First Floor)", "desc2": "", "qty": 61, "unit": "FT", "rate": 24, "cost": 0, "amount": 1464, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_13", "no": "102", "desc": "Plaster Ceiling L Box (First Floor)", "desc2": "", "qty": 80, "unit": "FT", "rate": 22, "cost": 0, "amount": 1760, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_14", "no": "103", "desc": "Plaster Ceiling U Box (First Floor)", "desc2": "", "qty": 58, "unit": "FT", "rate": 37, "cost": 0, "amount": 2146, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_15", "no": "104", "desc": "Conceal Track Light", "desc2": "", "qty": 1, "unit": "SET", "rate": 285, "cost": 0, "amount": 285, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_16", "no": "105", "desc": "Curtain Pelmet U-shape", "desc2": "", "qty": 4, "unit": "FT", "rate": 43, "cost": 0, "amount": 172, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_17", "no": "106", "desc": "Fan Hook (First Floor)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 70, "cost": 0, "amount": 140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_18", "no": "107", "desc": "Manhole 24\"", "desc2": "", "qty": 2, "unit": "NOS", "rate": 155, "cost": 0, "amount": 310, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s5_19", "no": "108", "desc": "Pendant Light Support (First Floor)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 70, "cost": 0, "amount": 140, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s6", "title": "Aluminium and Glass Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s6_0", "no": "109", "desc": "High Performance Fixed Glass Panel c/w 10mm Tempered Clear Glass and Aluminium Frame in p/c White Finish at Entertainment Room\nDimension : W3000 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 6600, "cost": 0, "amount": 6600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_1", "no": "110", "desc": "High Performance Sliding Door c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c White Finish at Entertainment Room\nDimension : W3415 H2700 (Max 6 Panels)", "desc2": "", "qty": 2, "unit": "SET", "rate": 11350, "cost": 0, "amount": 22700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_2", "no": "111", "desc": "12mm Frameless Tempered Clear Glass c/w Round Corner Design at Staircase Area\nDimension : W2700 H1000 R100", "desc2": "", "qty": 1, "unit": "SET", "rate": 2550, "cost": 0, "amount": 2550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_3", "no": "112", "desc": "High Performance Sliding Window c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c White Finish at Kitchen\nDimension : W2700 H600 (Max 3 panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 2550, "cost": 0, "amount": 2550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_4", "no": "113", "desc": "High Performance Sliding Window c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c White Finish at Kitchen\nDimension : W2100 H2100 (Max 3 panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 4240, "cost": 0, "amount": 4240, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_5", "no": "114", "desc": "Bi-Fold Folding Door c/w Frosted Glass and Aluminium Frame in p/c White Finish at Bathroom 5\nDimension : W800 H2100", "desc2": "", "qty": 1, "unit": "SET", "rate": 670, "cost": 0, "amount": 670, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_6", "no": "115", "desc": "Normal Type Top Hung Window c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c White Finish at Bathroom 5\nDimension : W600 H600", "desc2": "", "qty": 1, "unit": "SET", "rate": 470, "cost": 0, "amount": 470, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_7", "no": "116", "desc": "Fixed Glass Panel c/w 10mm Tempered Ultra Clear Fluted Glass at Master Bedroom\nDimension : W790 H3000", "desc2": "", "qty": 1, "unit": "SET", "rate": 3750, "cost": 0, "amount": 3750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_8", "no": "117", "desc": "Mirror c/w 5mm Clear Glass, 4G Aluminium Frame and Backlight Design in p/c Black Finish at Master Bedroom Walk-in-Wardrobe\nDimension : W700 H1800", "desc2": "", "qty": 1, "unit": "SET", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_9", "no": "118", "desc": "Mirror c/w 5mm Clear Glass and Both Sides LED Lighting Design at Master Bedroom Walk-in-Wardrobe\nDimension : W700 H1800", "desc2": "", "qty": 1, "unit": "SET", "rate": 3300, "cost": 0, "amount": 3300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_10", "no": "119", "desc": "Mirror c/w 5mm Clear Glass and Both Sides LED Lighting Design at Master Bathroom\nDimension : W540 H1800", "desc2": "", "qty": 1, "unit": "SET", "rate": 3750, "cost": 0, "amount": 3750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_11", "no": "120", "desc": "Fixed Glass Panel c/w 10mm Tempered Ultra Clear Fluted Glass at Master Bathroom\nDimension : W867 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 3400, "cost": 0, "amount": 3400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_12", "no": "121", "desc": "Sliding Door c/w 5mm Tempered Ultra Clear Fluted Glass and Aluminium Slim Line Frame in p/c Black Finish at Master Bathroom\nDimension : W900 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 3600, "cost": 0, "amount": 3600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_13", "no": "122", "desc": "Shower Screen Fixed Panel c/w 10mm Tempered Clear Glass and 4 sides PCB U Channel at Master Bathroom\nDimension : W600 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 960, "cost": 0, "amount": 960, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s6_14", "no": "123", "desc": "Mirror c/w 5mm Clear Glass, 4G Aluminium Frame and Backlight Design in p/c Black Finish at Bedroom 3\nDimension : W700 H1800", "desc2": "", "qty": 1, "unit": "SET", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s7", "title": "Flooring Work (SPC, Vinyl and Laminate)", "optional": false, "items": [{"type": "item", "id": "qt204r1_s7_0", "no": "124", "desc": "To Supply and Install 12mm Engineered Timber Flooring at Ground Floor Entertainment Room and Study Area, Staircase and First Floor (Except: Bathroom, Master Wardrobe and Bedroom 3)", "desc2": "", "qty": 906, "unit": "SQFT", "rate": 28, "cost": 0, "amount": 25368, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s7_1", "no": "125", "desc": "To Supply and Install 90mm HT Solid Wood Skirting at Ground Floor Entertainment Room and Study Area, Staircase and First Floor", "desc2": "", "qty": 66, "unit": "SQFT", "rate": 37.5, "cost": 0, "amount": 2475.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s7_2", "no": "126", "desc": "To Supply Labour to Lay Leveling Compound at Ground Floor Platform Area", "desc2": "", "qty": 354, "unit": "SQFT", "rate": 3.3, "cost": 0, "amount": 1168.2, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s7_3", "no": "127", "desc": "To Supply and Install Carpet at Master Wardrobe and Bedroom 3\nDimension : 255sqft\nCode : LIN06", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3550, "cost": 0, "amount": 3550, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s8", "title": "Awning Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s8_0", "no": "128", "desc": "To Supply and Install Aluminium Awning c/w Aluminium Ceiling Board at Laundry\nSkylight 5mm Clear Glass + 1.52mm Clear Pvb + 5mm Clear Glass\nDimension : 6800mm x 1360mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 15600, "cost": 0, "amount": 15600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s8_1", "no": "129", "desc": "To Supply and Install Aluminium Awning c/w Aluminium Ceiling Board at Car Porch\nComposite 4mm, Deco Panel Ceiling 0.40mm\nDimension : 10782mm x 1800mm, 3740mm x 3600mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 25100, "cost": 0, "amount": 25100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s8_2", "no": "130", "desc": "To Supply and Install Aluminium Awning c/w Aluminium Ceiling Board at Terrace\nComposite 4mm, Deco Panel Ceiling 0.40mm\nDimension : 10782mm x 1800mm, 3740mm x 3600mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 20500, "cost": 0, "amount": 20500, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s9", "title": "Painting & Touch Up Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s9_0", "no": "131", "desc": "To Supply Labour and Material\n- Exterior Wall - Jotun Paint (3 Color)\n- Interior Wall - Jotun Majestic (3 Color)\n- Door, Door Frame - Included (1 Color)\n- Ceiling - (1 Color)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 29000, "cost": 0, "amount": 29000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s9_1", "no": "132", "desc": "To Supply Labour and Material for Sandblasting The Exterior Fencing Wall at Terrace", "desc2": "", "qty": 456, "unit": "SQFT", "rate": 20, "cost": 0, "amount": 9120, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s9_2", "no": "133", "desc": "To Supply and Lay Vasari Lime Paint at TV Console Feature Wall\nDimension : 472sqft", "desc2": "", "qty": 1, "unit": "JOB", "rate": 5670, "cost": 0, "amount": 5670, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s10", "title": "Carpentry Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s10_0", "no": "134", "desc": "Shoe Cabinet c/w Solid Plywood In Selected Laminated Finish at Car Porch\nDimension : Shoe Cabinet - W2400 H1200 D450", "desc2": "", "qty": 1, "unit": "SET", "rate": 4450, "cost": 0, "amount": 4450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_1", "no": "135", "desc": "Feature Wall c/w Solid Plywood In Selected Laminated Finish at Foyer\nDimension : Feature Wall - 115sqft", "desc2": "", "qty": 1, "unit": "SET", "rate": 6750, "cost": 0, "amount": 6750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_2", "no": "136", "desc": "Shoe Cabinet with Shelving c/w Solid Plywood In Selected Laminated Finish at Foyer\nDimension : Shoe Cabinet with Shelving - W2500 D400 H2775", "desc2": "", "qty": 1, "unit": "SET", "rate": 6800, "cost": 0, "amount": 6800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_3", "no": "137", "desc": "TV Console with Feature Wall c/w Solid Plywood In Selected Laminated Finish at Living\nDimension : TV Console - W4200 D600 H200 / Feature Wall - 357sqft", "desc2": "", "qty": 1, "unit": "SET", "rate": 34560, "cost": 0, "amount": 34560, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_4", "no": "138", "desc": "Feature Wall with Hidden Door and Base Cabinet c/w Solid Plywood In Selected Laminated Finish at Dry Kitchen\nDimension : Feature Wall with Hidden Door - W4785 H3000 / Base Cabinet - W1950 D600 H900", "desc2": "", "qty": 1, "unit": "SET", "rate": 29980, "cost": 0, "amount": 29980, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_5", "no": "139", "desc": "Ceiling Feature Wall c/w Solid Plywood In Selected Laminated Finish at Staircase\nDimension : Ceiling Feature Wall - L8580 W2240 H225", "desc2": "", "qty": 1, "unit": "SET", "rate": 17800, "cost": 0, "amount": 17800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_6", "no": "140", "desc": "Staircase Cabinet c/w Solid Plywood In Selected Laminated Finish\nDimension : Staircase Cabinet - W3130 H2100", "desc2": "", "qty": 1, "unit": "SET", "rate": 15400, "cost": 0, "amount": 15400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_7", "no": "141", "desc": "Staircase Railing c/w Solid Plywood In Selected Laminated Finish\nDimension : Railling - 32sqft", "desc2": "", "qty": 1, "unit": "SET", "rate": 2350, "cost": 0, "amount": 2350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_8", "no": "142", "desc": "To Supply and Install Marble KSM2081 Venish Grey at Staircase", "desc2": "", "qty": 1, "unit": "SET", "rate": 13120, "cost": 0, "amount": 13120, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_9", "no": "143", "desc": "Tall Cabinet c/w Solid Plywood In Selected Laminated Finish at Entertainment Area\nDimension : Tall Cabinet with Openshelf - W3290 D450 H2850", "desc2": "", "qty": 1, "unit": "SET", "rate": 12820, "cost": 0, "amount": 12820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_10", "no": "144", "desc": "Island c/w Solid Plywood In Selected Laminated Finish at Kitchen\nDimension : Island - W2100 D900 H900 / Marble KSM2081 Venish Grey Table Top", "desc2": "", "qty": 1, "unit": "SET", "rate": 15650, "cost": 0, "amount": 15650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_11", "no": "145", "desc": "Kitchen Cabinet c/w Solid Plywood In Selected Laminated Finished and Aluminium Carcass Base Cabinet\nDimension : Base Cabinet - W3300+2280 D600 H870 / Tall Cabinet - W445+600+1020 D750 H3000", "desc2": "", "qty": 1, "unit": "SET", "rate": 46900, "cost": 0, "amount": 46900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_12", "no": "146", "desc": "Hidden Door c/w Solid Plywood In Selected Laminated Finish\nDimension : Hidden Door Include Hinges and Door Handle - W900 H3000", "desc2": "", "qty": 1, "unit": "SET", "rate": 5100, "cost": 0, "amount": 5100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_13", "no": "147", "desc": "Laundry Cabinet c/w Solid Plywood In Selected Laminated Finish\nDimension : Tall Cabinet - W1040 D600 H2700 / Base Cabinet - W850 D600 H1000", "desc2": "", "qty": 1, "unit": "SET", "rate": 16800, "cost": 0, "amount": 16800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_14", "no": "148", "desc": "Bedhead and Side Table c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Bedhead with Curve Design - W4835 H1300", "desc2": "", "qty": 1, "unit": "SET", "rate": 11150, "cost": 0, "amount": 11150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_15", "no": "149", "desc": "Feature Wall c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Feature Wall - W1890 H3000", "desc2": "", "qty": 1, "unit": "SET", "rate": 9150, "cost": 0, "amount": 9150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_16", "no": "150", "desc": "Sliding Door c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Sliding Door Include Track and Door Handle - W900 H300", "desc2": "", "qty": 1, "unit": "SET", "rate": 4700, "cost": 0, "amount": 4700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_17", "no": "151", "desc": "Wardrobe c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Wardrobe - W3690 D600 H3000", "desc2": "", "qty": 1, "unit": "SET", "rate": 26800, "cost": 0, "amount": 26800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_18", "no": "152", "desc": "Wardrobe and Dressing Table c/w Solid Plywood In Selected Laminated Finish at Master Bedroom Walk-in Wardrobe\nDimension : Open Wardrobe - W2712 D600 H2700 / Closed Wardrobe - W2810 D600 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 36200, "cost": 0, "amount": 36200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_19", "no": "153", "desc": "Vanity c/w Solid Plywood In Selected Laminated Finish at Master Bathroom\nDimension : Bottom Cabinet - W1500 D500 H500", "desc2": "", "qty": 1, "unit": "SET", "rate": 6100, "cost": 0, "amount": 6100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_20", "no": "154", "desc": "Bedhead and Side Table c/w Solid Plywood In Selected Laminated Finish at Bedroom 2\nDimension : Bedhead - W2862 H1000", "desc2": "", "qty": 1, "unit": "SET", "rate": 4400, "cost": 0, "amount": 4400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_21", "no": "155", "desc": "Openshelf, Wardrobe and Study Table c/w Solid Plywood In Selected Laminated Finish at Bedroom 2", "desc2": "", "qty": 1, "unit": "SET", "rate": 9000, "cost": 0, "amount": 9000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_22", "no": "156", "desc": "Wardrobe c/w Solid Plywood In Selected Laminated Finish at Bedroom 3\nDimension : Open Wardrobe - W2490 D600 H2700 / Closed Wardrobe - W2500 D600 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 44900, "cost": 0, "amount": 44900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s10_23", "no": "157", "desc": "Carpentry Touch Up Work", "desc2": "", "qty": 1, "unit": "LS", "rate": 6000, "cost": 0, "amount": 6000, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s11", "title": "Curtains and Blinds", "optional": false, "items": [{"type": "item", "id": "qt204r1_s11_0", "no": "158", "desc": "To Supply and Install Day and Night Curtain at Living\nDimension : 7763mm x 3150mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 2900, "cost": 0, "amount": 2900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_1", "no": "159", "desc": "To Supply and Install Day and Night Curtain at Entertainment Room\nDimension : 8630mm x 3150mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 3370, "cost": 0, "amount": 3370, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_2", "no": "160", "desc": "To Supply and Install Day and Night Curtain at Bedroom 4\nDimension : 1800mm x 3000mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 3370, "cost": 0, "amount": 3370, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_3", "no": "161", "desc": "To Supply and Install Venation Blinds at Kitchen\nDimension : 2300mm x 2330mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 2220, "cost": 0, "amount": 2220, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_4", "no": "162", "desc": "To Supply and Install Day and Night Curtain at Master Bedroom\nDimension : 6142mm x 3000mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 2320, "cost": 0, "amount": 2320, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_5", "no": "163", "desc": "To Supply and Install Venation Blinds at Master Bedroom\nDimension : 900mm x 2500mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 940, "cost": 0, "amount": 940, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_6", "no": "164", "desc": "To Supply and Install Day and Night Curtain at Walk-in Wardrobe\nDimension : 2810mm x 3000mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 1100, "cost": 0, "amount": 1100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_7", "no": "165", "desc": "To Supply and Install Day and Night Curtain at Bedroom 2\nDimension : 2830mm x 3000mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 1100, "cost": 0, "amount": 1100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s11_8", "no": "166", "desc": "To Supply and Install Venation Blinds at Bedroom 3\nDimension : 1210mm x 2280mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 1130, "cost": 0, "amount": 1130, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s12", "title": "Door and Door Frame", "optional": false, "items": [{"type": "item", "id": "qt204r1_s12_0", "no": "167", "desc": "To Supply and Install Semi-Solid Nyatoh Wood Door Panel Only c/w Lever Lock - Including Hinges and Mortics Lock\nDimension : W900 H2100", "desc2": "", "qty": 7, "unit": "SET", "rate": 700, "cost": 0, "amount": 4900, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s13", "title": "Autogate", "optional": false, "items": [{"type": "item", "id": "qt204r1_s13_0", "no": "168", "desc": "To Supply and Install Autogate\na) Trackless Folding Gate - Fully aluminium, 3 Years warranty\nb) Aluminium Side Gate - Basic design", "desc2": "", "qty": 1, "unit": "LS", "rate": 14200, "cost": 0, "amount": 14200, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s14", "title": "Pest Control", "optional": false, "items": [{"type": "item", "id": "qt204r1_s14_0", "no": "169", "desc": "Anti Termite Slab Injection + Soil Treatment at Extension Area\nc/w termite baiting system (during warranty period if active termite found)\n3 year warranty", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4300, "cost": 0, "amount": 4300, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s15", "title": "Landscape", "optional": false, "items": [{"type": "item", "id": "qt204r1_s15_0", "no": "170", "desc": "To Supply And Install 100mm Dia, Subsoil Piping System Inside 1 Feet Deep Inside Soil and Covered With 20mm Crushed Aggregate", "desc2": "", "qty": 85, "unit": "FT", "rate": 22.5, "cost": 0, "amount": 1912.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_1", "no": "171", "desc": "Site Cleaning", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1240, "cost": 0, "amount": 1240, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_2", "no": "172", "desc": "Garden PVC Edge", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 135, "cost": 0, "amount": 270, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_3", "no": "173", "desc": "Olive Tree", "desc2": "", "qty": 2, "unit": "NOS", "rate": 2550, "cost": 0, "amount": 5100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_4", "no": "174", "desc": "Pongamia Pinnata (Indian beech)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 490, "cost": 0, "amount": 980, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_5", "no": "175", "desc": "Monstera Deliciosa (Swiss cheese plant)", "desc2": "", "qty": 10, "unit": "NOS", "rate": 55.5, "cost": 0, "amount": 555.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_6", "no": "176", "desc": "Philodendron Selloum (Lacy-tree)", "desc2": "", "qty": 12, "unit": "NOS", "rate": 42.5, "cost": 0, "amount": 510.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_7", "no": "177", "desc": "Schefflera Aroboricola (Schefflera plant)", "desc2": "", "qty": 20, "unit": "NOS", "rate": 16.5, "cost": 0, "amount": 330.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_8", "no": "178", "desc": "Blechnum Gibbum (Dwarf tree fern)", "desc2": "", "qty": 6, "unit": "NOS", "rate": 42.5, "cost": 0, "amount": 255.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_9", "no": "179", "desc": "Aglaonema nitidum Silver Queen (Chinese evergreen)", "desc2": "", "qty": 20, "unit": "NOS", "rate": 20, "cost": 0, "amount": 400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_10", "no": "180", "desc": "Dracaena fragrans (Corn plant)", "desc2": "", "qty": 12, "unit": "NOS", "rate": 20, "cost": 0, "amount": 240, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_11", "no": "181", "desc": "Infinity edge Water Feature (Pond + Pump + UV + Biosand filter system)", "desc2": "", "qty": 1, "unit": "SET", "rate": 39075, "cost": 0, "amount": 39075, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s15_12", "no": "182", "desc": "Maintenance Garden Services - FOC", "desc2": "", "qty": 1, "unit": "LS", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s16", "title": "Item Supplies", "optional": false, "items": [{"type": "item", "id": "qt204r1_s16_0", "no": "183", "desc": "Stella - Led Spotlight Wide Angle - (10W) 3000K", "desc2": "", "qty": 7, "unit": "NOS", "rate": 53, "cost": 0, "amount": 371, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_1", "no": "184", "desc": "Stella - Led Spotlight Wide Angle - (10W) 4000K", "desc2": "", "qty": 3, "unit": "NOS", "rate": 53, "cost": 0, "amount": 159, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_2", "no": "185", "desc": "Stella - Led Spotlight Wide Angle - (12W) 3000K", "desc2": "", "qty": 19, "unit": "NOS", "rate": 73, "cost": 0, "amount": 1387, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_3", "no": "186", "desc": "Stella - Led Spotlight Wide Angle - (12W) 4000K", "desc2": "", "qty": 12, "unit": "NOS", "rate": 73, "cost": 0, "amount": 876, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_4", "no": "187", "desc": "Tico Black - Led Spotlight Casing Set With Mr16 Spotlight - (7W) 3000K", "desc2": "", "qty": 5, "unit": "NOS", "rate": 95, "cost": 0, "amount": 475, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_5", "no": "188", "desc": "Peri Box - Led Surface Spotlight - (12W) 3000K", "desc2": "", "qty": 5, "unit": "NOS", "rate": 110, "cost": 0, "amount": 550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_6", "no": "189", "desc": "Vanguard - Led Garden Spike Light - (3W) 3000K", "desc2": "", "qty": 6, "unit": "NOS", "rate": 135, "cost": 0, "amount": 810, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_7", "no": "190", "desc": "Icos - Led Mini Spotlight - (7W) 3000K", "desc2": "", "qty": 3, "unit": "NOS", "rate": 75, "cost": 0, "amount": 225, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_8", "no": "191", "desc": "Luna - Trimless Led Spotlight - (7W) 3000K", "desc2": "", "qty": 18, "unit": "NOS", "rate": 185, "cost": 0, "amount": 3330, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_9", "no": "192", "desc": "Elly & Jo 2(Black) - Led Multi-Spotlight (Anti Glare) - (7W) 3000K", "desc2": "", "qty": 8, "unit": "NOS", "rate": 190, "cost": 0, "amount": 1520, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_10", "no": "193", "desc": "Inscope 2 (Black) - Led Surface Mount Spotlight (Square) Double - (7W) 3000K", "desc2": "", "qty": 5, "unit": "NOS", "rate": 210, "cost": 0, "amount": 1050, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_11", "no": "194", "desc": "Pine+ - Led Wall Light Outdoor - (12W) 3000K", "desc2": "", "qty": 5, "unit": "NOS", "rate": 190, "cost": 0, "amount": 950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_12", "no": "195", "desc": "Mini Grid - Magnetic Rail Track - (1M)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 150, "cost": 0, "amount": 450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_13", "no": "196", "desc": "Mini Grid - Magnetic Rail Track - (2M)", "desc2": "", "qty": 7, "unit": "NOS", "rate": 300, "cost": 0, "amount": 2100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_14", "no": "197", "desc": "Mini Fit - Magnetic Track Light - (7W) 3000K", "desc2": "", "qty": 2, "unit": "NOS", "rate": 200, "cost": 0, "amount": 400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_15", "no": "198", "desc": "Mini Seet - Magnetic Multi-Spotlight - (7W) 3000K", "desc2": "", "qty": 6, "unit": "NOS", "rate": 300, "cost": 0, "amount": 1800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_16", "no": "199", "desc": "Mini Linear - Magnetic Linear Light - (16W) 3000K", "desc2": "", "qty": 5, "unit": "NOS", "rate": 365, "cost": 0, "amount": 1825, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_17", "no": "200", "desc": "Switching Power Supply 48V 300W - Magnetic Power Supply (300W)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 245, "cost": 0, "amount": 735, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_18", "no": "201", "desc": "Lumi - Led Spotlight Anti-Glare - (15W) 3000K", "desc2": "", "qty": 4, "unit": "NOS", "rate": 175, "cost": 0, "amount": 700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_19", "no": "202", "desc": "Mines - Led Staircase Lighting - (3W) 3000K", "desc2": "", "qty": 7, "unit": "NOS", "rate": 55, "cost": 0, "amount": 385, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_20", "no": "203", "desc": "Suno - Trimless Staircase Lighting - (1W) 3000K", "desc2": "", "qty": 4, "unit": "NOS", "rate": 285, "cost": 0, "amount": 1140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_21", "no": "204", "desc": "Led Strip - SMD2835 - 120 Chips - (14W/M) 3000K", "desc2": "", "qty": 9, "unit": "NOS", "rate": 85, "cost": 0, "amount": 765, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_22", "no": "205", "desc": "Sps Switching Power Supply 24V (Super Slim) - 200/24", "desc2": "", "qty": 9, "unit": "NOS", "rate": 100, "cost": 0, "amount": 900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_23", "no": "206", "desc": "Aluminium Profile Cabinet 90 Degree - Aluminium Profile Cabinet 10x15 with Wings (3M) - Silver Colour", "desc2": "", "qty": 16, "unit": "NOS", "rate": 60, "cost": 0, "amount": 960, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_24", "no": "207", "desc": "Membrance Light (Staircase) - 3000K", "desc2": "", "qty": 46.5, "unit": "FT", "rate": 100, "cost": 0, "amount": 4650.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_25", "no": "208", "desc": "Membrance Light (Wardrobe) - 3000K", "desc2": "", "qty": 53, "unit": "FT", "rate": 100, "cost": 0, "amount": 5300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_26", "no": "209", "desc": "LED Light Strip", "desc2": "", "qty": 1, "unit": "SET", "rate": 4700, "cost": 0, "amount": 4700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_27", "no": "210", "desc": "LED Light Power Supply", "desc2": "", "qty": 1, "unit": "SET", "rate": 2300, "cost": 0, "amount": 2300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_28", "no": "211", "desc": "16A 1 Gang 1 Way", "desc2": "", "qty": 7, "unit": "NOS", "rate": 18.5, "cost": 0, "amount": 129.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_29", "no": "212", "desc": "16A 1 Gang 2 Way", "desc2": "", "qty": 6, "unit": "NOS", "rate": 25, "cost": 0, "amount": 150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_30", "no": "213", "desc": "16A 2 Gang 1 Way", "desc2": "", "qty": 8, "unit": "NOS", "rate": 25.5, "cost": 0, "amount": 204.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_31", "no": "214", "desc": "16A 2 Gang 2 Way", "desc2": "", "qty": 3, "unit": "NOS", "rate": 35, "cost": 0, "amount": 105, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_32", "no": "215", "desc": "16A 3 Gang 1 Way", "desc2": "", "qty": 9, "unit": "NOS", "rate": 38.5, "cost": 0, "amount": 346.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_33", "no": "216", "desc": "10A 4 Gang 1 Way", "desc2": "", "qty": 6, "unit": "NOS", "rate": 52.5, "cost": 0, "amount": 315.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_34", "no": "217", "desc": "20A 1 Gang 1 Way Double Pole Switch with Blue LED Indicator (Water Heater/Air-Cond)", "desc2": "", "qty": 15, "unit": "NOS", "rate": 50, "cost": 0, "amount": 750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_35", "no": "218", "desc": "16A 1 Gang Doorbell Switch", "desc2": "", "qty": 1, "unit": "NOS", "rate": 25.5, "cost": 0, "amount": 25.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_36", "no": "219", "desc": "16A 1 Gang Auto Gate Push Button / Momentary Switch", "desc2": "", "qty": 1, "unit": "NOS", "rate": 29, "cost": 0, "amount": 29, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_37", "no": "220", "desc": "13A 1 Gang Flat Pin Switched Socket Outlet", "desc2": "", "qty": 58, "unit": "NOS", "rate": 23, "cost": 0, "amount": 1334, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_38", "no": "221", "desc": "15A Round Pin Switched Socket Outlet", "desc2": "", "qty": 2, "unit": "NOS", "rate": 40, "cost": 0, "amount": 80, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_39", "no": "222", "desc": "1 Gang TV Outlet", "desc2": "", "qty": 1, "unit": "NOS", "rate": 29, "cost": 0, "amount": 29, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_40", "no": "223", "desc": "1 Gang Telephone Outlet (RJ11)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 31, "cost": 0, "amount": 31, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_41", "no": "224", "desc": "1 Gang Data Outlet Cat 6 (RJ45)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 65.5, "cost": 0, "amount": 65.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_42", "no": "225", "desc": "Alpha KS1-3B/60 Ceiling Fan 60\"", "desc2": "", "qty": 3, "unit": "NOS", "rate": 700, "cost": 0, "amount": 2100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_43", "no": "226", "desc": "Alpha VC3-3B/52 Ceiling Fan 52\"", "desc2": "", "qty": 5, "unit": "NOS", "rate": 530, "cost": 0, "amount": 2650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_44", "no": "227", "desc": "Alpha Ceiling Fan 28\"", "desc2": "", "qty": 1, "unit": "NOS", "rate": 400, "cost": 0, "amount": 400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_45", "no": "228", "desc": "Panasonic Ceiling Mount Sirocco Ventilation Fan 24cm", "desc2": "", "qty": 4, "unit": "NOS", "rate": 500, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_46", "no": "229", "desc": "Foyer Wall Light", "desc2": "", "qty": 1, "unit": "NOS", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_47", "no": "230", "desc": "Master Bedroom Pendant Light", "desc2": "", "qty": 1, "unit": "NOS", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_48", "no": "231", "desc": "Bedroom 2 Pendant Light", "desc2": "", "qty": 1, "unit": "NOS", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_49", "no": "232", "desc": "XiaoMi Smart Camera", "desc2": "", "qty": 6, "unit": "NOS", "rate": 260, "cost": 0, "amount": 1560, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_50", "no": "233", "desc": "XiaoMi Outdoor Camera BW500", "desc2": "", "qty": 5, "unit": "NOS", "rate": 360, "cost": 0, "amount": 1800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_51", "no": "234", "desc": "DAIKIN Wall Hung Air Conditioner Inverter 1.5HP", "desc2": "", "qty": 5, "unit": "NOS", "rate": 2300, "cost": 0, "amount": 11500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_52", "no": "235", "desc": "DAIKIN Wall Hung Air Conditioner Inverter 2.0HP", "desc2": "", "qty": 1, "unit": "NOS", "rate": 3450, "cost": 0, "amount": 3450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_53", "no": "236", "desc": "DAIKIN Cassette Air Conditioner Inverter 3.0HP", "desc2": "", "qty": 2, "unit": "NOS", "rate": 5550, "cost": 0, "amount": 11100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_54", "no": "237", "desc": "Bareno Intelligient Water Closet LUX WI-164W", "desc2": "", "qty": 1, "unit": "NOS", "rate": 5550, "cost": 0, "amount": 5550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_55", "no": "238", "desc": "Sorento ABS Rain Shower Head Chrome Surface SRTSH22712", "desc2": "", "qty": 1, "unit": "NOS", "rate": 95, "cost": 0, "amount": 95, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_56", "no": "239", "desc": "Sorento Close-Coupled WC Washdown With Rimless Flushing Technology SRTW8840-RL", "desc2": "", "qty": 1, "unit": "NOS", "rate": 1150, "cost": 0, "amount": 1150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_57", "no": "240", "desc": "Sorento Hand Bidet c/w 1.2m Flexible Hose SRT72-CR", "desc2": "", "qty": 1, "unit": "NOS", "rate": 66, "cost": 0, "amount": 66, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_58", "no": "241", "desc": "Sorento Toilet Paper Holder S/Steel 304 SRT2303-HP", "desc2": "", "qty": 1, "unit": "NOS", "rate": 95, "cost": 0, "amount": 95, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_59", "no": "242", "desc": "Sorento Floor Trap SRT384-6", "desc2": "", "qty": 1, "unit": "NOS", "rate": 55, "cost": 0, "amount": 55, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_60", "no": "243", "desc": "Sorento Ceramic Tile Drainage 150x150mm SRT6638", "desc2": "", "qty": 2, "unit": "NOS", "rate": 58, "cost": 0, "amount": 116, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_61", "no": "244", "desc": "Sorento Hose Bib Tap SRTWT2205", "desc2": "", "qty": 4, "unit": "NOS", "rate": 85, "cost": 0, "amount": 340, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_62", "no": "245", "desc": "Sorento Stop Valve 1/2\" S/Steel 304", "desc2": "", "qty": 5, "unit": "NOS", "rate": 235, "cost": 0, "amount": 1175, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_63", "no": "246", "desc": "Sorento Bottle Trap Brass BT011", "desc2": "", "qty": 1, "unit": "NOS", "rate": 260, "cost": 0, "amount": 260, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_64", "no": "247", "desc": "Abagno 330mm Ceiling Shower Arm LS-22-330C-BN", "desc2": "", "qty": 1, "unit": "NOS", "rate": 180, "cost": 0, "amount": 180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_65", "no": "248", "desc": "Abagno S/Steel 300mm Rain Shower SQ-3012P-BN", "desc2": "", "qty": 1, "unit": "NOS", "rate": 300, "cost": 0, "amount": 300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_66", "no": "249", "desc": "Sorento Concealed Bath-Shower Mixer SRTWT8252GM", "desc2": "", "qty": 1, "unit": "NOS", "rate": 510, "cost": 0, "amount": 510, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_67", "no": "250", "desc": "Abagno Wall Union LS-35-45-BN", "desc2": "", "qty": 1, "unit": "NOS", "rate": 110, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_68", "no": "251", "desc": "Sorento 3 Functions Hand Shower SRTSS5726-GM", "desc2": "", "qty": 1, "unit": "NOS", "rate": 180, "cost": 0, "amount": 180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_69", "no": "252", "desc": "Sorento Two Way Tap SRTWT5844-GM", "desc2": "", "qty": 1, "unit": "NOS", "rate": 180, "cost": 0, "amount": 180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_70", "no": "253", "desc": "Sorento S/Steel Hand Bidet SRT95SS-GM", "desc2": "", "qty": 1, "unit": "NOS", "rate": 130, "cost": 0, "amount": 130, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_71", "no": "254", "desc": "Bareno 30\" Double Tower Bar BD270730-BGM", "desc2": "", "qty": 1, "unit": "NOS", "rate": 290, "cost": 0, "amount": 290, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_72", "no": "255", "desc": "Abagno S/Steel Paper Holder PH-505-BN", "desc2": "", "qty": 1, "unit": "NOS", "rate": 180, "cost": 0, "amount": 180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_73", "no": "256", "desc": "Abagno 4 Hooks Hanger RH-7503-5-BN", "desc2": "", "qty": 1, "unit": "NOS", "rate": 140, "cost": 0, "amount": 140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_74", "no": "257", "desc": "Abagno Brass Single Hook RH-7101-BN", "desc2": "", "qty": 1, "unit": "NOS", "rate": 70, "cost": 0, "amount": 70, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_75", "no": "258", "desc": "Sorento 700mm Acrylic Bathtub + Sorento Free Standing Mixer Tap + Water Pump SRTBT1865-17", "desc2": "", "qty": 1, "unit": "NOS", "rate": 7950, "cost": 0, "amount": 7950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_76", "no": "259", "desc": "Bareno Super Single Jumbo Bowl Granite Sink c/w Drainage and Overflow GN7951B", "desc2": "", "qty": 2, "unit": "NOS", "rate": 1720, "cost": 0, "amount": 3440, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_77", "no": "260", "desc": "Bareno Brass 360 Swivel Spout with Pull-Out Spray Sink Mixer Brass Matt Black", "desc2": "", "qty": 2, "unit": "NOS", "rate": 590, "cost": 0, "amount": 1180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_78", "no": "261", "desc": "ECOWARE Three Side Double Basket with Undermount Soft Close Slide - Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 1010, "cost": 0, "amount": 1010, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_79", "no": "262", "desc": "ECOWARE Three Side Dish Basket with Undermount Soft Close Slide - Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 730, "cost": 0, "amount": 730, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_80", "no": "263", "desc": "ECOWARE Three Side Basket with Undermount Soft Close Slide - Black", "desc2": "", "qty": 2, "unit": "NOS", "rate": 550, "cost": 0, "amount": 1100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_81", "no": "264", "desc": "ECOWARE Magic Corner Basket with Soft Closing Slide - Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 1880, "cost": 0, "amount": 1880, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_82", "no": "265", "desc": "ECOWARE VS ENVI Single Bin Size 10L, Lava Grey", "desc2": "", "qty": 1, "unit": "NOS", "rate": 350, "cost": 0, "amount": 350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_83", "no": "266", "desc": "ECOWARE Multi Function Three Layer Basket with Undermount Soft-Closing Slide - Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 630, "cost": 0, "amount": 630, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_84", "no": "267", "desc": "Falcon Solid Safe (Korea) H38E (Digital Only)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 1050, "cost": 0, "amount": 1050, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_85", "no": "268", "desc": "Falcon Solid Safe (Korea) F-V380E", "desc2": "", "qty": 1, "unit": "NOS", "rate": 4730, "cost": 0, "amount": 4730, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_86", "no": "269", "desc": "750mm x 1500mm Floor Tiles at Living, Dining, Kitchen and Bedroom 4", "desc2": "", "qty": 82, "unit": "PIECES", "rate": 210, "cost": 0, "amount": 17220, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_87", "no": "270", "desc": "600mm x 1200mm Wall and Floor Tiles at Master Bathroom", "desc2": "", "qty": 62, "unit": "PIECES", "rate": 90, "cost": 0, "amount": 5580, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_88", "no": "271", "desc": "600mm x 1200mm Tiles for Feature Wall at Master Bathroom", "desc2": "", "qty": 10, "unit": "PIECES", "rate": 110, "cost": 0, "amount": 1100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_89", "no": "272", "desc": "600mm x 1200mm Floor Tiles at Terrace", "desc2": "", "qty": 72, "unit": "PIECES", "rate": 90, "cost": 0, "amount": 6480, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_90", "no": "273", "desc": "600mm x 1200mm Wall Tiles at Kitchen", "desc2": "", "qty": 38, "unit": "PIECES", "rate": 110, "cost": 0, "amount": 4180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s16_91", "no": "274", "desc": "200mm x 200mm Floor Tiles at Kitchen", "desc2": "", "qty": 590, "unit": "PIECES", "rate": 5.5, "cost": 0, "amount": 3245.0, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s17", "title": "Renovation Work Submission", "optional": false, "items": [{"type": "item", "id": "qt204r1_s17_0", "no": "275", "desc": "Architect Submission", "desc2": "", "qty": 1, "unit": "JOB", "rate": 8500, "cost": 0, "amount": 8500, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s18", "title": "Miscellaneous Work", "optional": false, "items": [{"type": "item", "id": "qt204r1_s18_0", "no": "276", "desc": "To Supply 4 Waste Bins to Clear Debris During Renovation Period", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1000, "cost": 0, "amount": 1000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s18_1", "no": "277", "desc": "To Supply and Lay Floorgard Mat Floor Protection 1 Times During Renovation Period", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2000, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s18_2", "no": "278", "desc": "To Supply Labour and Material to Clean The Entire Unit 2 Times (in the middle and the end of renovation period)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2000, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s19", "title": "Omission", "optional": false, "items": [{"type": "item", "id": "qt204r1_s19_0", "no": "279", "desc": "To Supply and Install Inlet and Outlet Water Piping for Robot Vacuum at Wet Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": -800, "cost": 0, "amount": -800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_1", "no": "280", "desc": "To Supply and Install New 2.0hp AC Copper Refrigerant Piping at Entertainment Room", "desc2": "", "qty": 1, "unit": "JOB", "rate": -3710, "cost": 0, "amount": -3710, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_2", "no": "281", "desc": "To Supply and Modify Existing AC Copper Refrigerant Piping at Ground Floor and Living Area", "desc2": "", "qty": 2, "unit": "JOB", "rate": -800, "cost": 0, "amount": -1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_3", "no": "282", "desc": "To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Bedroom 2, Bedroom 3, Bedroom 4 and Walk-in Wardrobe", "desc2": "", "qty": 4, "unit": "JOB", "rate": -600, "cost": 0, "amount": -2400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_4", "no": "283", "desc": "12mm Frameless Tempered Clear Glass c/w Round Corner Design at Staircase Area", "desc2": "", "qty": 1, "unit": "SET", "rate": -2550, "cost": 0, "amount": -2550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_5", "no": "284", "desc": "Mirror c/w 5mm Clear Glass, 4G Aluminium Frame and Backlight Design in p/c Black Finish at Master Bedroom Walk-in Wardrobe", "desc2": "", "qty": 1, "unit": "SET", "rate": -800, "cost": 0, "amount": -800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_6", "no": "285", "desc": "Mirror c/w 5mm Clear Glass, 4G Aluminium Frame and Backlight Design in p/c Black Finish at Bathroom 3", "desc2": "", "qty": 1, "unit": "SET", "rate": -800, "cost": 0, "amount": -800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_7", "no": "286", "desc": "To Supply and Install 12mm Engineered Timber Flooring at Ground Floor Entertainment Room and Study Area, Staircase and First Floor", "desc2": "", "qty": 906, "unit": "SQFT", "rate": -28, "cost": 0, "amount": -25368, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_8", "no": "287", "desc": "To Supply Labour to Lay Leveling Compound at Ground Floor Platform Area", "desc2": "", "qty": 354, "unit": "SQFT", "rate": -3.3, "cost": 0, "amount": -1168.2, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_9", "no": "288", "desc": "To Supply and Install Carpet at Master Wardrobe and Bedroom 3", "desc2": "", "qty": 1, "unit": "JOB", "rate": -3550, "cost": 0, "amount": -3550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_10", "no": "289", "desc": "To Supply and Lay Vasari Lime Paint at TV Console Feature Wall", "desc2": "", "qty": 1, "unit": "JOB", "rate": -5670, "cost": 0, "amount": -5670, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_11", "no": "290", "desc": "Staircase Railing c/w Solid Plywood In Selected Laminated Finish", "desc2": "", "qty": 1, "unit": "SET", "rate": -2350, "cost": 0, "amount": -2350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_12", "no": "291", "desc": "To Supply and Install Marble KSM2081 Venish Grey at Staircase", "desc2": "", "qty": 1, "unit": "SET", "rate": -13120, "cost": 0, "amount": -13120, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_13", "no": "292", "desc": "Island c/w Solid Plywood In Selected Laminated Finish at Kitchen", "desc2": "", "qty": 1, "unit": "SET", "rate": -15650, "cost": 0, "amount": -15650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_14", "no": "293", "desc": "Kitchen Cabinet c/w Solid Plywood In Selected Laminated Finished and Aluminium Carcass Base Cabinet", "desc2": "", "qty": 1, "unit": "SET", "rate": -46900, "cost": 0, "amount": -46900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_15", "no": "294", "desc": "Hidden Door c/w Solid Plywood In Selected Laminated Finish", "desc2": "", "qty": 1, "unit": "SET", "rate": -5100, "cost": 0, "amount": -5100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_16", "no": "295", "desc": "Vanity c/w Solid Plywood In Selected Laminated Finish at Master Bathroom", "desc2": "", "qty": 1, "unit": "SET", "rate": -6100, "cost": 0, "amount": -6100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_17", "no": "296", "desc": "Omission of Supply Items - All supply items previously included are omitted from this quotation (INZ-QUO-00204)", "desc2": "", "qty": 1, "unit": "LS", "rate": -153994, "cost": 0, "amount": -153994, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s19_18", "no": "297", "desc": "Architect Submission", "desc2": "", "qty": 1, "unit": "JOB", "rate": -8500, "cost": 0, "amount": -8500, "foc": false, "focRate": 0}]}, {"id": "qt204r1_s20", "title": "Variation Order", "optional": false, "items": [{"type": "item", "id": "qt204r1_s20_0", "no": "298", "desc": "To Demolish Floor Tiles and Wall Tiles c/w Patch Plaster Work at Bathroom 3", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3350, "cost": 0, "amount": 3350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_1", "no": "299", "desc": "To Core a Round Hole for Cooker Hood Ducting at Maid Bathroom", "desc2": "", "qty": 1, "unit": "JOB", "rate": 450, "cost": 0, "amount": 450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_2", "no": "300", "desc": "To Lay Wall Compound at Staircase and Family Hall", "desc2": "", "qty": 1, "unit": "JOB", "rate": 8000, "cost": 0, "amount": 8000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_3", "no": "301", "desc": "To Replace Damage Wall Tiles for Changing Shower Head and Wash Basin at Bathroom 4 and Bathroom 2", "desc2": "", "qty": 2, "unit": "JOB", "rate": 750, "cost": 0, "amount": 1500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_4", "no": "302", "desc": "To Supply Labour and Fitting to Change Sanitary Ware at Bathroom 2 and Bathroom 4", "desc2": "", "qty": 2, "unit": "NOS", "rate": 175, "cost": 0, "amount": 350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_5", "no": "303", "desc": "Eyeball/Downlight/Surface Lighting Point", "desc2": "", "qty": 2, "unit": "NOS", "rate": 100, "cost": 0, "amount": 200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_6", "no": "304", "desc": "LED Light Point", "desc2": "", "qty": 13, "unit": "NOS", "rate": 60, "cost": 0, "amount": 780, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_7", "no": "305", "desc": "Exhaust Fan Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 110, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_8", "no": "306", "desc": "Sensor Install", "desc2": "", "qty": 9, "unit": "SET", "rate": 90, "cost": 0, "amount": 810, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_9", "no": "307", "desc": "Hanging Light Install at Dining", "desc2": "", "qty": 1, "unit": "NOS", "rate": 200, "cost": 0, "amount": 200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_10", "no": "308", "desc": "Hanging Light Install at Kitchen", "desc2": "", "qty": 2, "unit": "NOS", "rate": 80, "cost": 0, "amount": 160, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_11", "no": "309", "desc": "Garden Light Install", "desc2": "", "qty": 8, "unit": "NOS", "rate": 40, "cost": 0, "amount": 320, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_12", "no": "310", "desc": "Exhaust Fan Install", "desc2": "", "qty": 1, "unit": "NOS", "rate": 40, "cost": 0, "amount": 40, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_13", "no": "311", "desc": "Waterproof Resin Cable Joint", "desc2": "", "qty": 5, "unit": "SET", "rate": 185, "cost": 0, "amount": 925, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_14", "no": "312", "desc": "Move Aircond Power Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 150, "cost": 0, "amount": 150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_15", "no": "313", "desc": "Cad 6 Data Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 450, "cost": 0, "amount": 450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_16", "no": "314", "desc": "TV Console Loose Cable", "desc2": "", "qty": 1, "unit": "NOS", "rate": 370, "cost": 0, "amount": 370, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_17", "no": "315", "desc": "Wall Box 3Phase Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 2500, "cost": 0, "amount": 2500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_18", "no": "316", "desc": "Neutral Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 930, "cost": 0, "amount": 930, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_19", "no": "317", "desc": "Sensor Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 320, "cost": 0, "amount": 320, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_20", "no": "318", "desc": "Wall Light Install", "desc2": "", "qty": 19, "unit": "NOS", "rate": 30, "cost": 0, "amount": 570, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_21", "no": "319", "desc": "Power Track Install", "desc2": "", "qty": 1, "unit": "NOS", "rate": 110, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_22", "no": "320", "desc": "13 Amp Power Socket Point", "desc2": "", "qty": 21, "unit": "NOS", "rate": 170, "cost": 0, "amount": 3570, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_23", "no": "321", "desc": "To Supply and Install New 3.0hp AC Copper Refrigerant Piping at Living", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3850, "cost": 0, "amount": 3850, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_24", "no": "322", "desc": "To Supply and Install New 2.5hp AC Copper Refrigerant Piping at Study Area", "desc2": "", "qty": 1, "unit": "JOB", "rate": 930, "cost": 0, "amount": 930, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_25", "no": "323", "desc": "To Supply Labour and Fitting to Install 1.0-1.5hp Wall-mounted AC at Bedroom 2, Bedroom 3, Bedroom 4 and Walk-in Wardrobe", "desc2": "", "qty": 4, "unit": "JOB", "rate": 470, "cost": 0, "amount": 1880, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_26", "no": "324", "desc": "H Profile Install (Ground Floor)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 370, "cost": 0, "amount": 370, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_27", "no": "325", "desc": "Partition Feature Wall at Bedroom 4", "desc2": "", "qty": 1, "unit": "SET", "rate": 2400, "cost": 0, "amount": 2400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_28", "no": "326", "desc": "Round Shape Ceiling (First Floor)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3600, "cost": 0, "amount": 3600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_29", "no": "327", "desc": "H Profile Install (First Floor)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 370, "cost": 0, "amount": 370, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_30", "no": "328", "desc": "Manhole 24\" at Bathroom 1", "desc2": "", "qty": 1, "unit": "JOB", "rate": 155, "cost": 0, "amount": 155, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_31", "no": "329", "desc": "12mm Frameless Tempered Super Clear Glass c/w Round Corner Design at Staircase Area", "desc2": "", "qty": 1, "unit": "SET", "rate": 5550, "cost": 0, "amount": 5550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_32", "no": "330", "desc": "Shower Screen Fixed Panel c/w 10mm Tempered Clear Glass and 4sides PCB U Channel at Bathroom 4", "desc2": "", "qty": 1, "unit": "SET", "rate": 1100, "cost": 0, "amount": 1100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_33", "no": "331", "desc": "Mirror c/w 5mm Clear Glass, 4G Aluminium Frame in p/c Black Finish at Bathroom 2", "desc2": "", "qty": 1, "unit": "SET", "rate": 670, "cost": 0, "amount": 670, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_34", "no": "332", "desc": "Mirror c/w 5mm Clear Glass, 4G Aluminium Frame in p/c Black Finish at Bathroom 4", "desc2": "", "qty": 1, "unit": "SET", "rate": 370, "cost": 0, "amount": 370, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_35", "no": "333", "desc": "Shower Glass with Swing Door c/w 10mm Tempered Clear Glass at Master Bathroom", "desc2": "", "qty": 1, "unit": "SET", "rate": 1500, "cost": 0, "amount": 1500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_36", "no": "334", "desc": "To Supply and Install 12mm Engineered Timber Flooring at Ground Floor Entertainment Room, Study Area, Staircase and First Floor (Except Bathroom and Bedroom 3)", "desc2": "", "qty": 1276, "unit": "SQFT", "rate": 28, "cost": 0, "amount": 35728, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_37", "no": "335", "desc": "To Supply Labour to Lay Leveling Compound at Ground Floor Platform Area and Bathroom 3", "desc2": "", "qty": 390, "unit": "SQFT", "rate": 3.3, "cost": 0, "amount": 1287.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_38", "no": "336", "desc": "To Supply and Install Staircase Landing", "desc2": "", "qty": 21, "unit": "PIECES", "rate": 370, "cost": 0, "amount": 7770, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_39", "no": "337", "desc": "To Supply and Lay Vasari Lime Paint at Bedroom Wall", "desc2": "", "qty": 200, "unit": "SQFT", "rate": 8, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_40", "no": "338", "desc": "To Supply Labour and Material for Sandblasting The Exterior Fencing Front and Back Wall at Terrace", "desc2": "", "qty": 126, "unit": "SQFT", "rate": 20, "cost": 0, "amount": 2520, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_41", "no": "339", "desc": "To Supply and Lay Vasari Lime Paint at Staircase High Wall", "desc2": "", "qty": 230, "unit": "SQFT", "rate": 12, "cost": 0, "amount": 2760, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_42", "no": "340", "desc": "To Supply and Lay Vasari Lime Paint at Family Hall", "desc2": "", "qty": 672, "unit": "SQFT", "rate": 9, "cost": 0, "amount": 6048, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_43", "no": "341", "desc": "To Exchange KSM3052 Volakas Dining Table Top and Backsplash to Marble KSM3058 Arizona White at Dining", "desc2": "", "qty": 1, "unit": "SET", "rate": 9900, "cost": 0, "amount": 9900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_44", "no": "342", "desc": "To Supply and Install Marble KSM2081 Venish Grey at Staircase", "desc2": "", "qty": 1, "unit": "SET", "rate": 18000, "cost": 0, "amount": 18000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_45", "no": "343", "desc": "Island c/w Solid Plywood In Selected Laminated Finish at Kitchen - c/w Quartz Stone Table Top", "desc2": "", "qty": 1, "unit": "SET", "rate": 16750, "cost": 0, "amount": 16750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_46", "no": "344", "desc": "Kitchen Cabinet c/w Solid Plywood In Selected Laminated Finished and Aluminium Carcass Base Cabinet at Kitchen - c/w Quartz Stone Table Top", "desc2": "", "qty": 1, "unit": "SET", "rate": 34000, "cost": 0, "amount": 34000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_47", "no": "345", "desc": "Vanity Cabinet Full Body c/w Plywood Door at Master Bathroom", "desc2": "", "qty": 1, "unit": "SET", "rate": 7600, "cost": 0, "amount": 7600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_48", "no": "346", "desc": "Vanity Cabinet Full Body c/w 4G Door & Side Panels at Bathroom 3 - c/w Quartz Table Top", "desc2": "", "qty": 1, "unit": "SET", "rate": 3000, "cost": 0, "amount": 3000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_49", "no": "347", "desc": "Dressing Table, Side Table, Platform, Tall Cabinet and Open Cabinet c/w Solid Plywood In Selected Laminated Finished at Bedroom 4", "desc2": "", "qty": 1, "unit": "SET", "rate": 13000, "cost": 0, "amount": 13000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_50", "no": "348", "desc": "Vanity Cabinet Carcass and Mirror Feature Wall c/w Solid Plywood In Selected Laminated Finish at Bathroom 4 - c/w Quartz Table Top", "desc2": "", "qty": 1, "unit": "SET", "rate": 4500, "cost": 0, "amount": 4500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_51", "no": "349", "desc": "Marble KSM2081 Venish Grey at Cabinet Top and Master Bedroom Wardrobe", "desc2": "", "qty": 1, "unit": "SET", "rate": 9400, "cost": 0, "amount": 9400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_52", "no": "350", "desc": "Marble KSM2081 Venish Grey for Side Table at Master Bedroom", "desc2": "", "qty": 1, "unit": "SET", "rate": 1280, "cost": 0, "amount": 1280, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_53", "no": "351", "desc": "Family Hall Feature Wall c/w Hafele Hinges", "desc2": "", "qty": 1, "unit": "SET", "rate": 7000, "cost": 0, "amount": 7000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_54", "no": "352", "desc": "Staircase Spray Paint", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3400, "cost": 0, "amount": 3400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_55", "no": "353", "desc": "Solid Wood Panel at Staircase Area", "desc2": "", "qty": 1, "unit": "SET", "rate": 6000, "cost": 0, "amount": 6000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_56", "no": "354", "desc": "Upgrade Sliding Door Accessories", "desc2": "", "qty": 3, "unit": "SET", "rate": 1800, "cost": 0, "amount": 5400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_57", "no": "355", "desc": "Upgrade Laminate to Lamitak Salt Microcement, Lamitak Staffa Creame and Formica Ice Onyx", "desc2": "", "qty": 1, "unit": "LS", "rate": 8300, "cost": 0, "amount": 8300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_58", "no": "356", "desc": "Upgrade Curtain Fabric (Material)", "desc2": "", "qty": 1, "unit": "LS", "rate": 4500, "cost": 0, "amount": 4500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_59", "no": "357", "desc": "To Supply and Install Timber Door Frame at Maid Room", "desc2": "", "qty": 1, "unit": "SET", "rate": 1280, "cost": 0, "amount": 1280, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_60", "no": "358", "desc": "Sprinkle for Planter Box", "desc2": "", "qty": 1, "unit": "JOB", "rate": 8000, "cost": 0, "amount": 8000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_61", "no": "359", "desc": "Round Shape 3w Underwater 12V WW", "desc2": "", "qty": 6, "unit": "NOS", "rate": 430, "cost": 0, "amount": 2580, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_62", "no": "360", "desc": "Portova C/Fan", "desc2": "", "qty": 5, "unit": "NOS", "rate": 470, "cost": 0, "amount": 2350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_63", "no": "361", "desc": "Eyeball Fitting", "desc2": "", "qty": 30, "unit": "NOS", "rate": 16.5, "cost": 0, "amount": 495.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_64", "no": "362", "desc": "4000k LED Bulb", "desc2": "", "qty": 30, "unit": "NOS", "rate": 10, "cost": 0, "amount": 300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_65", "no": "363", "desc": "4000k LED Cob Strip Light", "desc2": "", "qty": 6, "unit": "NOS", "rate": 31.5, "cost": 0, "amount": 189.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_66", "no": "364", "desc": "24V Switching Mode Power Supply", "desc2": "", "qty": 8, "unit": "NOS", "rate": 33.5, "cost": 0, "amount": 268.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_67", "no": "365", "desc": "24V Glozone Switching Mode Power Supply", "desc2": "", "qty": 2, "unit": "NOS", "rate": 31.5, "cost": 0, "amount": 63.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_68", "no": "366", "desc": "Alpha Racer 5B/40\" Ceiling Fan - Matt White", "desc2": "", "qty": 3, "unit": "NOS", "rate": 425, "cost": 0, "amount": 1275, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_69", "no": "367", "desc": "Alpha Racer 5B/48\" Ceiling Fan - Matt White", "desc2": "", "qty": 1, "unit": "NOS", "rate": 470, "cost": 0, "amount": 470, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_70", "no": "368", "desc": "Houm Ceiling Mount Ventilator Silver Panel & Black Plastic Housing", "desc2": "", "qty": 2, "unit": "NOS", "rate": 180, "cost": 0, "amount": 360, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_71", "no": "369", "desc": "Alpha Kona 16\" DC Motor Corner Fan - Matt White", "desc2": "", "qty": 2, "unit": "NOS", "rate": 450, "cost": 0, "amount": 900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_72", "no": "370", "desc": "6500k RD Surface Light", "desc2": "", "qty": 3, "unit": "NOS", "rate": 35.5, "cost": 0, "amount": 106.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_73", "no": "371", "desc": "Stella - Led Spotlight Wide Angle - (10W) 3000K", "desc2": "", "qty": 6, "unit": "NOS", "rate": 53.5, "cost": 0, "amount": 321.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_74", "no": "372", "desc": "Stella - Led Spotlight Wide Angle - (10W) 4000K", "desc2": "", "qty": 4, "unit": "NOS", "rate": 53.5, "cost": 0, "amount": 214.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_75", "no": "373", "desc": "Stella - Led Spotlight Wide Angle - (12W) 3000K", "desc2": "", "qty": 25, "unit": "NOS", "rate": 72.5, "cost": 0, "amount": 1812.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_76", "no": "374", "desc": "Stella - Led Spotlight Wide Angle - (12W) 4000K", "desc2": "", "qty": 13, "unit": "NOS", "rate": 72.5, "cost": 0, "amount": 942.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_77", "no": "375", "desc": "Mini Grid - Magnetic Rail Track - (1M)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 450, "cost": 0, "amount": 450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_78", "no": "376", "desc": "Mini Grid - Magnetic Rail Track - (2M)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 2100, "cost": 0, "amount": 2100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_79", "no": "377", "desc": "Mini Seet - Magnetic Multi-Spotlight - (7W) 3000K", "desc2": "", "qty": 8, "unit": "NOS", "rate": 370, "cost": 0, "amount": 2960, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_80", "no": "378", "desc": "Switching Power Supply 48V 300W - Magnetic Power Supply (300W)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 245, "cost": 0, "amount": 245, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_81", "no": "379", "desc": "Led Strip - SMD2835 - 120 Chips - (14W/M) 3000K", "desc2": "", "qty": 20, "unit": "NOS", "rate": 170, "cost": 0, "amount": 3400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_82", "no": "380", "desc": "Membrance Light (Staircase) - 3000K", "desc2": "", "qty": 46, "unit": "FT", "rate": 122, "cost": 0, "amount": 5612, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_83", "no": "381", "desc": "Membrance Light (Wardrobe) - 3000K", "desc2": "", "qty": 43, "unit": "FT", "rate": 100, "cost": 0, "amount": 4300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_84", "no": "382", "desc": "Aldi (12W) Led Spotlight Casing Set with MR16 Spotlight (3000k)", "desc2": "", "qty": 7, "unit": "NOS", "rate": 155, "cost": 0, "amount": 1085, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_85", "no": "383", "desc": "Aldi (12W) Led Spotlight Casing Set with MR16 Spotlight (Smart)", "desc2": "", "qty": 14, "unit": "NOS", "rate": 280, "cost": 0, "amount": 3920, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_86", "no": "384", "desc": "Tico (12W) Led Spotlight Casing Set with MR16 Spotlight (Smart) - Black", "desc2": "", "qty": 5, "unit": "NOS", "rate": 280, "cost": 0, "amount": 1400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_87", "no": "385", "desc": "Icos (7W) Led Mini Spotlight (3000k)", "desc2": "", "qty": 5, "unit": "NOS", "rate": 75.5, "cost": 0, "amount": 377.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_88", "no": "386", "desc": "Icos (7W) Led Mini Spotlight (4000k)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 75.5, "cost": 0, "amount": 75.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_89", "no": "387", "desc": "Nova (12W) Trimless Led Spotlight (Smart)", "desc2": "", "qty": 12, "unit": "NOS", "rate": 330, "cost": 0, "amount": 3960, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_90", "no": "388", "desc": "Nova (12W) Trimless Led Spotlight (3000k)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 310, "cost": 0, "amount": 620, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_91", "no": "389", "desc": "Panex (28W) Led Surface Mount Panel Light (4000k)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 72.5, "cost": 0, "amount": 217.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_92", "no": "390", "desc": "Round Wall Light (12W) Led Wall Light Outdoor (3000k)", "desc2": "", "qty": 5, "unit": "NOS", "rate": 190, "cost": 0, "amount": 950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_93", "no": "391", "desc": "Bucky (10W) Led Track Light (3000k)", "desc2": "", "qty": 1, "unit": "NOS", "rate": 80, "cost": 0, "amount": 80, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_94", "no": "392", "desc": "Mini Fit (12W) Magnetic Track Light (Smart)", "desc2": "", "qty": 5, "unit": "NOS", "rate": 380, "cost": 0, "amount": 1900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_95", "no": "393", "desc": "Switching Power Supply 48V (300W) Magnetic Power Supply", "desc2": "", "qty": 3, "unit": "NOS", "rate": 250, "cost": 0, "amount": 750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_96", "no": "394", "desc": "Vanguard (8W) Led Garden Spike Light", "desc2": "", "qty": 9, "unit": "NOS", "rate": 200, "cost": 0, "amount": 1800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_97", "no": "395", "desc": "Staircase Light (3W) 3000k", "desc2": "", "qty": 6, "unit": "NOS", "rate": 55.5, "cost": 0, "amount": 333.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_98", "no": "396", "desc": "Exterior Wall Washer 1000mm IP65 (Smart)", "desc2": "", "qty": 9, "unit": "NOS", "rate": 255, "cost": 0, "amount": 2295, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_99", "no": "397", "desc": "SPS Switching Power Supply 24V 300/24 (Super Slim Version)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 145, "cost": 0, "amount": 435, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_100", "no": "398", "desc": "Mini Grid (1M) Magnetic Rail Track", "desc2": "", "qty": 1, "unit": "NOS", "rate": 150, "cost": 0, "amount": 150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_101", "no": "399", "desc": "Mini Grid (2M) Magnetic Rail Track", "desc2": "", "qty": 1, "unit": "NOS", "rate": 300, "cost": 0, "amount": 300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_102", "no": "400", "desc": "Mini Fit (3W) Magnetic Track Light (3000k)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 135, "cost": 0, "amount": 270, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_103", "no": "401", "desc": "Led Strip (14W) 3000k", "desc2": "", "qty": 35, "unit": "NOS", "rate": 100, "cost": 0, "amount": 3500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_104", "no": "402", "desc": "Led Strip (14W) Outdoor 3000k", "desc2": "", "qty": 5, "unit": "NOS", "rate": 150, "cost": 0, "amount": 750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_105", "no": "403", "desc": "Sps Switching Power Supply 24V 200/24 (Super Slim Version)", "desc2": "", "qty": 26, "unit": "NOS", "rate": 100, "cost": 0, "amount": 2600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_106", "no": "404", "desc": "Aluminium Profile Ceiling H-Shape (3M) - Sliver", "desc2": "", "qty": 1, "unit": "NOS", "rate": 110, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_107", "no": "405", "desc": "Houm Superdryer SD-250 DC", "desc2": "", "qty": 1, "unit": "NOS", "rate": 2950, "cost": 0, "amount": 2950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_108", "no": "406", "desc": "Alpha Koko G2 3B/56\" Ceiling Fan - Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 470, "cost": 0, "amount": 470, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_109", "no": "407", "desc": "Alpha V3 3B/28'' LED + DC Ceiling Fan - Matt Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 400, "cost": 0, "amount": 400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_110", "no": "408", "desc": "Alpha Haru 3B/40\" DC Ceiling Fan - Black", "desc2": "", "qty": 1, "unit": "NOS", "rate": 400, "cost": 0, "amount": 400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_111", "no": "409", "desc": "Deka Tiny 16'' Fiero Ceiling & Wall Fan - Black", "desc2": "", "qty": 2, "unit": "NOS", "rate": 365, "cost": 0, "amount": 730, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_112", "no": "410", "desc": "Houm SV-90-D1 Ceiling Mount Ventilator Silver Panel & Black Plastic Housing", "desc2": "", "qty": 2, "unit": "NOS", "rate": 175, "cost": 0, "amount": 350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_113", "no": "411", "desc": "Airegard AE-120-D1 Ventilator with Single Speed 120CFM", "desc2": "", "qty": 1, "unit": "NOS", "rate": 390, "cost": 0, "amount": 390, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_114", "no": "412", "desc": "M3 1G1W Smoky Black", "desc2": "", "qty": 7, "unit": "NOS", "rate": 18.5, "cost": 0, "amount": 129.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_115", "no": "413", "desc": "M3 1G2W Smoky Black", "desc2": "", "qty": 6, "unit": "NOS", "rate": 25, "cost": 0, "amount": 150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_116", "no": "414", "desc": "M3 2G1W Smoky Black", "desc2": "", "qty": 8, "unit": "NOS", "rate": 25.5, "cost": 0, "amount": 204.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_117", "no": "415", "desc": "M3 2G2W Smoky Black", "desc2": "", "qty": 4, "unit": "NOS", "rate": 35, "cost": 0, "amount": 140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_118", "no": "416", "desc": "M3 3G1W Smoky Black", "desc2": "", "qty": 16, "unit": "NOS", "rate": 40, "cost": 0, "amount": 640, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_119", "no": "417", "desc": "M3 3G2W Smoky Black", "desc2": "", "qty": 2, "unit": "NOS", "rate": 51.5, "cost": 0, "amount": 103.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_120", "no": "418", "desc": "M3 4G1W Smoky Black", "desc2": "", "qty": 6, "unit": "NOS", "rate": 52.5, "cost": 0, "amount": 315.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_121", "no": "419", "desc": "M3 20A Heater Switch", "desc2": "", "qty": 16, "unit": "NOS", "rate": 50, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_122", "no": "420", "desc": "M3 1G Auto Gate", "desc2": "", "qty": 1, "unit": "NOS", "rate": 29, "cost": 0, "amount": 29, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_123", "no": "421", "desc": "M3 13A 1G", "desc2": "", "qty": 72, "unit": "NOS", "rate": 23.5, "cost": 0, "amount": 1692.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_124", "no": "422", "desc": "M3 13A Universal with Charging", "desc2": "", "qty": 13, "unit": "NOS", "rate": 140, "cost": 0, "amount": 1820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_125", "no": "423", "desc": "M3 1G Data Outlet", "desc2": "", "qty": 2, "unit": "NOS", "rate": 65.5, "cost": 0, "amount": 131.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_126", "no": "424", "desc": "Spike Cap Gu-10-Black (Casing Only)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 125, "cost": 0, "amount": 375, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_127", "no": "425", "desc": "Seed Gu10 Warm White 7w Bulb", "desc2": "", "qty": 3, "unit": "NOS", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_128", "no": "426", "desc": "Surface Black Ceiling Light Small Milo Tin Gu10 Fitting", "desc2": "", "qty": 3, "unit": "NOS", "rate": 50, "cost": 0, "amount": 150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_129", "no": "427", "desc": "Brillant Gu10 Bulb 9w Warmwhite", "desc2": "", "qty": 3, "unit": "NOS", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_130", "no": "428", "desc": "320s 24v 14w/M 3000k Cob LED Strip", "desc2": "", "qty": 31, "unit": "NOS", "rate": 22.5, "cost": 0, "amount": 697.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_131", "no": "429", "desc": "320s 24v 14w/M 4000k Cob LED Strip", "desc2": "", "qty": 2, "unit": "NOS", "rate": 22.5, "cost": 0, "amount": 45.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_132", "no": "430", "desc": "High Quality 24v Driver Power Supply 100w Esn", "desc2": "", "qty": 15, "unit": "NOS", "rate": 33.5, "cost": 0, "amount": 502.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_133", "no": "431", "desc": "High Quality 24v Driver Power Supply 300w Esn", "desc2": "", "qty": 9, "unit": "NOS", "rate": 55.5, "cost": 0, "amount": 499.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_134", "no": "432", "desc": "800mm Retouch Blk Colour", "desc2": "", "qty": 1, "unit": "NOS", "rate": 175, "cost": 0, "amount": 175, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_135", "no": "433", "desc": "13A Multiple Socket", "desc2": "", "qty": 3, "unit": "NOS", "rate": 32.5, "cost": 0, "amount": 97.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_136", "no": "434", "desc": "Type A+C Socket", "desc2": "", "qty": 1, "unit": "NOS", "rate": 70, "cost": 0, "amount": 70, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_137", "no": "435", "desc": "IP65 320D 24v 3000k Cob LED Strip", "desc2": "", "qty": 10, "unit": "NOS", "rate": 22.5, "cost": 0, "amount": 225.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_138", "no": "436", "desc": "Waterproof Connector", "desc2": "", "qty": 10, "unit": "PIECES", "rate": 0, "cost": 0, "amount": 0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_139", "no": "437", "desc": "24v Driver Power Supply 300w Esn", "desc2": "", "qty": 1, "unit": "NOS", "rate": 55.5, "cost": 0, "amount": 55.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_140", "no": "438", "desc": "Spike Cap Gu-10-Black (Casing Only)", "desc2": "", "qty": 3, "unit": "UNIT", "rate": 125, "cost": 0, "amount": 375, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_141", "no": "439", "desc": "Wire-Copper 6 Meter x 3", "desc2": "", "qty": 18, "unit": "M", "rate": 20, "cost": 0, "amount": 360, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_142", "no": "440", "desc": "Spike Cap Gu-10-Black (Casing Only)", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 125, "cost": 0, "amount": 250, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_143", "no": "441", "desc": "Wire-Copper 5 Meter x 2", "desc2": "", "qty": 10, "unit": "M", "rate": 20, "cost": 0, "amount": 200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_144", "no": "442", "desc": "Spike Cap Gu-10-Black (Casing Only)", "desc2": "", "qty": 3, "unit": "UNIT", "rate": 125, "cost": 0, "amount": 375, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_145", "no": "443", "desc": "Wire-Copper 3 Meter x 3", "desc2": "", "qty": 9, "unit": "M", "rate": 20, "cost": 0, "amount": 180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_146", "no": "444", "desc": "Dess Light Updown 10W", "desc2": "", "qty": 5, "unit": "UNIT", "rate": 175, "cost": 0, "amount": 875, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_147", "no": "445", "desc": "13A Universal with Charging", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 125, "cost": 0, "amount": 125, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_148", "no": "446", "desc": "Master Bedroom (Single Door) x 5 Sets - Hafele Loox Driver, 6Way Pin Distributor, Loox Led 12V, Sensor for Sliding Door, Loox Led Ribbon 8mm 12V", "desc2": "", "qty": 1, "unit": "LS", "rate": 2222.5, "cost": 0, "amount": 2222.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_149", "no": "447", "desc": "Master Bedroom (Double Door) x 2 Sets - Hafele Loox Driver, 6Way Pin Distributor, Loox Led 12V, Sensor for Sliding Door, Loox Led Ribbon 8mm 12V", "desc2": "", "qty": 1, "unit": "LS", "rate": 1099, "cost": 0, "amount": 1099, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_150", "no": "448", "desc": "Bedroom (Double Door) x 2 Sets - Hafele Loox Driver, 6Way Pin Distributor, Loox Led 12V, Sensor for Sliding Door, Loox Led Ribbon 8mm 12V", "desc2": "", "qty": 1, "unit": "LS", "rate": 1099, "cost": 0, "amount": 1099, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_151", "no": "449", "desc": "DAIKIN Wall Hung Air Conditioner Inverter 1.5HP", "desc2": "", "qty": 3, "unit": "NOS", "rate": 2450, "cost": 0, "amount": 7350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_152", "no": "450", "desc": "DAIKIN Wall Hung Air Conditioner Inverter 2.0HP", "desc2": "", "qty": 1, "unit": "NOS", "rate": 3650, "cost": 0, "amount": 3650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_153", "no": "451", "desc": "DAIKIN Cassette Air Conditioner Inverter 2.5HP", "desc2": "", "qty": 1, "unit": "NOS", "rate": 4750, "cost": 0, "amount": 4750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_154", "no": "452", "desc": "DAIKIN Wall Hung Air Conditioner Inverter 3.0HP", "desc2": "", "qty": 1, "unit": "NOS", "rate": 5350, "cost": 0, "amount": 5350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_155", "no": "453", "desc": "DAIKIN Inverter 1.0HP 5 Star Wall Unit", "desc2": "", "qty": 1, "unit": "NOS", "rate": 1950, "cost": 0, "amount": 1950, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_156", "no": "454", "desc": "Giono T6300-3-M Floor-Standing Bathtub Mixer - Black Nickel", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 2000, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_157", "no": "455", "desc": "Bareno W11602BW Dynamic Vortex Flush Intelligent Water Closet", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 3200, "cost": 0, "amount": 3200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_158", "no": "456", "desc": "Blanco 526653 Mida-S Sink Mixer - 3/8\" (Black)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 1850, "cost": 0, "amount": 1850, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_159", "no": "457", "desc": "Blanco 526001 Silgranit Sink Subline 700-U - 3/8\" (Black)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 2450, "cost": 0, "amount": 2450, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_160", "no": "458", "desc": "Blanco 525793 Catris-S Flexio Sink Mixer - 3/8\" (Black)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 4100, "cost": 0, "amount": 4100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_161", "no": "459", "desc": "Cam Heud Single Bowl SUS 304 Stainless Steel Handmade Small Radius Sink", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 550, "cost": 0, "amount": 550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_162", "no": "460", "desc": "Saniware SWP-SS-304-3940 SUS 304 Stainless Steel Pillar Sink Tap", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 180, "cost": 0, "amount": 180, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_163", "no": "461", "desc": "Cam Single Bowl Sus 304 Stainless Steel Handmade Small Radius Sink", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 660, "cost": 0, "amount": 660, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_164", "no": "462", "desc": "Giono 19712-L-BN Tall Basin Mixer with Top Mounted Valve - Black Nickel", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 720, "cost": 0, "amount": 720, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_165", "no": "463", "desc": "Giono 19712-L-BN Tall Basin Mixer with Top Mounted Valve - Brass Chrome", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 660, "cost": 0, "amount": 660, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_166", "no": "464", "desc": "Johnson Suisse Gemelli Rectangular Undercounter Basin - White", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 520, "cost": 0, "amount": 520, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_167", "no": "465", "desc": "Giono GN-2280 1 1/4\" SUS 304 Stainless Steel Waste with Dustbin - Chrome", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 70, "cost": 0, "amount": 70, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_168", "no": "466", "desc": "Aimer AMSB-55 SUS 304 Stainless Steel Hand Bidet Set - Black Nickel", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 120, "cost": 0, "amount": 120, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_169", "no": "467", "desc": "Aimer AMAV-9256 Lever Handle Angle Valve - Black Nickel", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 55, "cost": 0, "amount": 55, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_170", "no": "468", "desc": "RINOCON Tornado Flush One-Piece Water Closet (S-Trap 250mm) - White", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 750, "cost": 0, "amount": 1500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_171", "no": "469", "desc": "Johnson Suisse Gemelli Rectangular Under Counter Basin - White", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 520, "cost": 0, "amount": 520, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_172", "no": "470", "desc": "GIONO GN-2280 SUS 304 Stainless Steel 1 1/4\" Basin Waste With Dustbin - Chrome", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 66.5, "cost": 0, "amount": 66.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_173", "no": "471", "desc": "AIMER Basin Mixer - Brass Chrome", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 420, "cost": 0, "amount": 420, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_174", "no": "472", "desc": "ABAGNO 2-Ways Exposed Shower Column - Brass Chrome", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 650, "cost": 0, "amount": 650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_175", "no": "473", "desc": "Abagno AR-6430-BN 76cm Single Towel Bar - Black Nickel (Master Bath)", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 125, "cost": 0, "amount": 250, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_176", "no": "474", "desc": "Abagno PH-501-BN Paper Holder - Black Nickel (Master Bath)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 120, "cost": 0, "amount": 120, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_177", "no": "475", "desc": "Abagno AR-6430-SC 76cm Single Towel Bar - S/Steel Chrome (Bath 2 & Bath 4)", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 120, "cost": 0, "amount": 240, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_178", "no": "476", "desc": "Abagno BS-5097-BP Basket Shelf With Hook (Bath 2)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 135, "cost": 0, "amount": 135, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_179", "no": "477", "desc": "ROCCONI Full Cover Toilet Paper Holder - S/Steel Polish (Bath 2 & Maid Bath)", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 55.5, "cost": 0, "amount": 111.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_180", "no": "478", "desc": "Abagno PH-501-BP Paper Holder - S/Steel Polish (Bath 4)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 78, "cost": 0, "amount": 78, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_181", "no": "479", "desc": "GIONO SUS304 S/Steel Flexible Towel Shelf With Hook - Polish (Maid Bath)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 145, "cost": 0, "amount": 145, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_182", "no": "480", "desc": "ROCCONI RCN8711 Corner Rack With Basket - S/Steel Polish (Maid Bath)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 78, "cost": 0, "amount": 78, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_183", "no": "481", "desc": "KleenGard Deluxe In-Sink Food Disposal (Kitchen)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 1790, "cost": 0, "amount": 1790, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_184", "no": "482", "desc": "ECOWARE Magic Corner Basket with Soft Closing Slide - Black", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 1220, "cost": 0, "amount": 1220, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_185", "no": "483", "desc": "T204 Aluminium Profile Handle - 3.66MT Black", "desc2": "", "qty": 50, "unit": "UNIT", "rate": 21.5, "cost": 0, "amount": 1075.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_186", "no": "484", "desc": "Up and Down Storage Kit Elevator Basket with Tempered Glass and Soft Closing - Dark Grey", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 570, "cost": 0, "amount": 1140, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_187", "no": "485", "desc": "Aluminium Table Drawer - 600mm", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 640, "cost": 0, "amount": 1280, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_188", "no": "486", "desc": "Aluminium Cookware Storage Drawer - 600mm", "desc2": "", "qty": 2, "unit": "UNIT", "rate": 465, "cost": 0, "amount": 930, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_189", "no": "487", "desc": "Akaca Multi Function Base Unit - 400mm", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 550, "cost": 0, "amount": 550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_190", "no": "488", "desc": "Aluminium Deluxe Larder Pantry - 450mm", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 2250, "cost": 0, "amount": 2250, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_191", "no": "489", "desc": "Hafele S-Drawer H80/500mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 170, "cost": 0, "amount": 170, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_192", "no": "490", "desc": "Hafele S-Drawer H170/500mm", "desc2": "", "qty": 3, "unit": "SET", "rate": 210, "cost": 0, "amount": 630, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_193", "no": "491", "desc": "Blanco Rondo Silgranit Sink & Waste - Anthracite", "desc2": "", "qty": 1, "unit": "PIECES", "rate": 1790, "cost": 0, "amount": 1790, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_194", "no": "492", "desc": "Aegis S7 Safety Box (Digital Lock)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 15850, "cost": 0, "amount": 15850, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_195", "no": "493", "desc": "Templar UL3 Safety Box (Digital Lock)", "desc2": "", "qty": 1, "unit": "UNIT", "rate": 3650, "cost": 0, "amount": 3650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_196", "no": "494", "desc": "300mm x 600mm Tiles at Car Porch Area", "desc2": "", "qty": 104, "unit": "PIECES", "rate": 7, "cost": 0, "amount": 728, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_197", "no": "495", "desc": "600mm x 1200mm Tiles at Master Bathroom", "desc2": "", "qty": 6, "unit": "PIECES", "rate": 110, "cost": 0, "amount": 660, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_198", "no": "496", "desc": "600mm x 1200mm Tiles at Master Bedroom, Terrace and Laundry", "desc2": "", "qty": 166, "unit": "PIECES", "rate": 90, "cost": 0, "amount": 14940, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_199", "no": "497", "desc": "300mm x 600mm Tiles at Maid Room", "desc2": "", "qty": 67, "unit": "PIECES", "rate": 5, "cost": 0, "amount": 335, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_200", "no": "498", "desc": "200mm x 200mm Floor Tiles at Kitchen", "desc2": "", "qty": 570, "unit": "PIECES", "rate": 5.5, "cost": 0, "amount": 3135.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_201", "no": "499", "desc": "300mm x 600mm Tiles at Bathroom 2", "desc2": "", "qty": 56, "unit": "PIECES", "rate": 29, "cost": 0, "amount": 1624, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_202", "no": "500", "desc": "750mm x 1500mm Floor Tiles at Living, Dining, Kitchen and Bedroom 4", "desc2": "", "qty": 90, "unit": "PIECES", "rate": 210, "cost": 0, "amount": 18900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_203", "no": "501", "desc": "Ultra Color Plus for All Area", "desc2": "", "qty": 1, "unit": "JOB", "rate": 360, "cost": 0, "amount": 360, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_204", "no": "502", "desc": "Sofa", "desc2": "", "qty": 1, "unit": "SET", "rate": 14511.2, "cost": 0, "amount": 14511.2, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_205", "no": "503", "desc": "Dining Table - Oreo Grey Marble & Metal Leg", "desc2": "", "qty": 1, "unit": "SET", "rate": 14273.1, "cost": 0, "amount": 14273.1, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_206", "no": "504", "desc": "Dining Chair - Microfibre & Wood", "desc2": "", "qty": 6, "unit": "SET", "rate": 1889, "cost": 0, "amount": 11334, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_207", "no": "505", "desc": "Coffee Table (Original - Reclaimed Teak - 1200 X 600 X 340mm)", "desc2": "", "qty": 1, "unit": "SET", "rate": 2693.65, "cost": 0, "amount": 2693.65, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_208", "no": "506", "desc": "Coffee Table Black Reclaimed Teak (1000 X 280mm & 500 X 380mm)", "desc2": "", "qty": 1, "unit": "SET", "rate": 5480, "cost": 0, "amount": 5480, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_209", "no": "507", "desc": "Hanging Light - 1330x550x400", "desc2": "", "qty": 1, "unit": "NOS", "rate": 3779.1, "cost": 0, "amount": 3779.1, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_210", "no": "508", "desc": "Hanging Light - 650x570x4000", "desc2": "", "qty": 1, "unit": "NOS", "rate": 2942.1, "cost": 0, "amount": 2942.1, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_211", "no": "509", "desc": "Rug Light Brown", "desc2": "", "qty": 1, "unit": "PIECES", "rate": 4300, "cost": 0, "amount": 4300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_212", "no": "510", "desc": "Denson R9 Biometric Lever Lock Set (With APP Control)", "desc2": "", "qty": 2, "unit": "SET", "rate": 299, "cost": 0, "amount": 598, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_213", "no": "511", "desc": "Electronic Fireplace", "desc2": "", "qty": 1, "unit": "SET", "rate": 1700, "cost": 0, "amount": 1700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_214", "no": "512", "desc": "Xiaomi Outdoor Camera CW300 (White)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 189, "cost": 0, "amount": 567, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_215", "no": "513", "desc": "Xiaomi Outdoor Camera CW100 Dual EU", "desc2": "", "qty": 1, "unit": "NOS", "rate": 179, "cost": 0, "amount": 179, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_216", "no": "514", "desc": "Xiaomi Smart Camera (White)", "desc2": "", "qty": 4, "unit": "NOS", "rate": 219, "cost": 0, "amount": 876, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_217", "no": "515", "desc": "MicroSD Card 64GB", "desc2": "", "qty": 8, "unit": "NOS", "rate": 89, "cost": 0, "amount": 712, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_218", "no": "516", "desc": "Towel Rack", "desc2": "", "qty": 1, "unit": "SET", "rate": 2250, "cost": 0, "amount": 2250, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_219", "no": "517", "desc": "Jewelry Wardrobe Organizer", "desc2": "", "qty": 1, "unit": "SET", "rate": 1350, "cost": 0, "amount": 1350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_220", "no": "518", "desc": "Architect Submission", "desc2": "", "qty": 1, "unit": "JOB", "rate": 16500, "cost": 0, "amount": 16500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_221", "no": "519", "desc": "Defect Inspection", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1600, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt204r1_s20_222", "no": "520", "desc": "Special Discount", "desc2": "", "qty": 1, "unit": "LS", "rate": -670.45, "cost": 0, "amount": -670.45, "foc": false, "focRate": 0}]}], "pis": [], "payments": [], "invoices": []}; if(_ex){Object.assign(_ex,q);}else{_ql.push(q);} const _mi=QUOT_LIST.findIndex(qq=>qq.id===QID); if(_mi>=0){Object.assign(QUOT_LIST[_mi],q);}else{QUOT_LIST.push(q);} localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); console.log('[INZII] Migration v8: INZ-QUO-00204-R1 imported.'); })(); // โ”€โ”€ Migration v8: import INZ-QUO-00264-R3 โ”€โ”€ (function(){ const QID='INZ-QUO-00264-R3'; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); const _ex=_ql.find(q=>q.id===QID); if(_ex&&(_ex.sections||[]).length>0){return;} const q={"id": "INZ-QUO-00264-R3", "quotNo": "INZ-QUO-00264", "revision": 3, "client": "Koh Tiong Sim", "clientPhone": "+658914 5347", "remarks": "PJ1069 - Ms Chuang, Pulai", "date": "2025-11-05", "finalAmt": 687000, "totalAmt": 751910.5, "totalDisc": 64910.5, "taxAmt": 0, "handler": "Khang Cheng", "status": "Won", "wonDeal": "2025-11-05", "paymentTerm": "Design and Renovation (30%, 30%, 30%, 10%)", "termCondition": "Terms & Conditions - Construction Use", "designAgreement": "", "address": "", "sections": [{"id": "qt264r3_s0", "title": "Masonry Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s0_0", "no": "1", "desc": "To Provide Demolition and Hacking Work", "desc2": "", "qty": 1, "unit": "LS", "rate": 30000, "cost": 0, "amount": 30000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_1", "no": "2", "desc": "To Provide Minor Concrete, Erect Brick Wall and Plaster Work", "desc2": "", "qty": 1, "unit": "JOB", "rate": 13300, "cost": 0, "amount": 13300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_2", "no": "3", "desc": "To Erect Brick Wall to Seal Up and Raise Height Carporch Fence and Pillar c/w Skim Whole Fence", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3750, "cost": 0, "amount": 3750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_3", "no": "4", "desc": "To Construct New Carporch Pillar and Side Gate Wall", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2400, "cost": 0, "amount": 2400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_4", "no": "5", "desc": "To Patch Plaster and Touch Up After Demolition at Side Balcony Wall at Ground Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2670, "cost": 0, "amount": 2670, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_5", "no": "6", "desc": "To Erect Brick Wall and Lintel for Living Hall Window", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2550, "cost": 0, "amount": 2550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_6", "no": "7", "desc": "To Erect New Main Door Wall", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2000, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_7", "no": "8", "desc": "To Modify Foyer Wall to Feature Wall c/w Touch Up Damaged Wall", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2800, "cost": 0, "amount": 2800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_8", "no": "9", "desc": "To Construct New Staircase Step", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1350, "cost": 0, "amount": 1350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_9", "no": "10", "desc": "To Construct Pation Concrete Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 15500, "cost": 0, "amount": 15500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_10", "no": "11", "desc": "To Erect Brick Wall for Ground Floor New Bathroom, Store and Yard Area", "desc2": "", "qty": 1, "unit": "JOB", "rate": 6800, "cost": 0, "amount": 6800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_11", "no": "12", "desc": "To Construct Cement Render c/w Screeding Finished at Ground Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3350, "cost": 0, "amount": 3350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_12", "no": "13", "desc": "To Patch Plaster and Touch Up After Demolition at Ground Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 330, "cost": 0, "amount": 330, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_13", "no": "14", "desc": "To Core a Round Hole for Cooker Hood Ducting at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 11730, "cost": 0, "amount": 11730, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_14", "no": "15", "desc": "To Construct Concrete Island c/w Stainless Steel Table Top at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2600, "cost": 0, "amount": 2600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_15", "no": "16", "desc": "To Patch Plaster and Touch Up Window Wall and Bedroom Wall After Modify c/w New Lintel at First Floor", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1150, "cost": 0, "amount": 1150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_16", "no": "17", "desc": "To Erect Wall c/w Touch Up Door Frame at Bathroom 1", "desc2": "", "qty": 1, "unit": "JOB", "rate": 6780, "cost": 0, "amount": 6780, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_17", "no": "18", "desc": "Pad Footing c/w Evacation, Formwork, Y12 Steel bar, G25 Concrete (Dancing Room Extension)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 2050, "cost": 0, "amount": 4100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_18", "no": "19", "desc": "Ground Beam c/w Formwork, Y12 Steel bar, G25 Concrete (Dancing Room Extension)", "desc2": "", "qty": 17, "unit": "M", "rate": 585, "cost": 0, "amount": 9945, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_19", "no": "20", "desc": "Column c/w Formwork, Y12 Steel bar, G25 Concrete (Dancing Room Extension)", "desc2": "", "qty": 2, "unit": "NOS", "rate": 2990, "cost": 0, "amount": 5980, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_20", "no": "21", "desc": "Roof Beam c/w Formwork, Y12 Steel bar, G25 Concrete (Dancing Room Extension)", "desc2": "", "qty": 17, "unit": "M", "rate": 585, "cost": 0, "amount": 9945, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_21", "no": "22", "desc": "Ground Slab c/w Excavation, A7 BRC, G25 Concrete (Dancing Room Extension)", "desc2": "", "qty": 252, "unit": "SQFT", "rate": 25, "cost": 0, "amount": 6300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_22", "no": "23", "desc": "Flat Roof Slab c/w Formwork, Y12 Steel bar, G25 Concrete, Waterproofing (Dancing Room Extension)", "desc2": "", "qty": 193, "unit": "SQFT", "rate": 55, "cost": 0, "amount": 10615, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_23", "no": "24", "desc": "Brick Wall 115mm c/w 25mm Cement and Sand Rendering, Skimcoat Finishing (Dancing Room Extension)", "desc2": "", "qty": 164, "unit": "SQFT", "rate": 30, "cost": 0, "amount": 4920, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_24", "no": "25", "desc": "Pad Footing c/w Evacation, Formwork, Y12 Steel bar, G25 Concrete (Kitchen Extension)", "desc2": "", "qty": 4, "unit": "NOS", "rate": 2050, "cost": 0, "amount": 8200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_25", "no": "26", "desc": "Ground Beam c/w Formwork, Y12 Steel bar, G25 Concrete (Kitchen Extension)", "desc2": "", "qty": 20.5, "unit": "M", "rate": 585, "cost": 0, "amount": 11992.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_26", "no": "27", "desc": "Column c/w Formwork, Y12 Steel bar, G25 Concrete (Kitchen Extension)", "desc2": "", "qty": 4, "unit": "NOS", "rate": 2990, "cost": 0, "amount": 11960, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_27", "no": "28", "desc": "Roof Beam c/w Formwork, Y12 Steel bar, G25 Concrete (Kitchen Extension)", "desc2": "", "qty": 20.5, "unit": "M", "rate": 585, "cost": 0, "amount": 11992.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_28", "no": "29", "desc": "Ground Slab c/w Excavation, A7 BRC, G25 Concrete (Kitchen Extension)", "desc2": "", "qty": 357, "unit": "SQFT", "rate": 25, "cost": 0, "amount": 8925, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_29", "no": "30", "desc": "Flat Roof Slab c/w Formwork, Y12 Steel bar, G25 Concrete, Waterproofing (Kitchen Extension)", "desc2": "", "qty": 285, "unit": "SQFT", "rate": 55, "cost": 0, "amount": 15675, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_30", "no": "31", "desc": "Brick Wall 115mm c/w 25mm Cement and Sand Rendering, Skimcoat Finishing (Kitchen Extension)", "desc2": "", "qty": 202, "unit": "SQFT", "rate": 30, "cost": 0, "amount": 6060, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_31", "no": "32", "desc": "Upstand Beam c/w Formwork, Y12 Steel bar, G25 Concrete (Balcony Extension)", "desc2": "", "qty": 4, "unit": "M", "rate": 585, "cost": 0, "amount": 2340, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_32", "no": "33", "desc": "Column c/w Formwork, Y12 Steel bar, G25 Concrete (Balcony Extension)", "desc2": "", "qty": 3, "unit": "NOS", "rate": 2990, "cost": 0, "amount": 8970, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_33", "no": "34", "desc": "Roof Beam c/w Formwork, Y12 Steel bar, G25 Concrete (Balcony Extension)", "desc2": "", "qty": 10, "unit": "M", "rate": 585, "cost": 0, "amount": 5850, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_34", "no": "35", "desc": "Brick Wall 115mm c/w 25mm Cement and Sand Rendering, Skimcoat Finishing (Balcony Extension)", "desc2": "", "qty": 568, "unit": "SQFT", "rate": 30, "cost": 0, "amount": 17040, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s0_35", "no": "36", "desc": "Flower Pot and Ventilation Block", "desc2": "", "qty": 1, "unit": "JOB", "rate": 16000, "cost": 0, "amount": 16000, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s1", "title": "Tiles Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s1_0", "no": "37", "desc": "To Supply Labour to Lay New Bark Brick Floor Tiles at Foyer (*Not Including Floor Tiles)\nDimension : 80sqft", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3470, "cost": 0, "amount": 3470, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s1_1", "no": "38", "desc": "To Supply Labour to Lay New 600x600mm Floor Tiles at Kitchen (*Not Including Floor Tiles)\nDimension : 506sqft", "desc2": "", "qty": 1, "unit": "JOB", "rate": 7650, "cost": 0, "amount": 7650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s1_2", "no": "39", "desc": "To Supply Labour to Lay New 600x600mm Floor Tiles and Wall Tiles at Bathroom 4 (*Not Including Tiles)\nc/w 3 Layers QuicSeal 104 Waterproofing", "desc2": "", "qty": 1, "unit": "JOB", "rate": 8000, "cost": 0, "amount": 8000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s1_3", "no": "40", "desc": "To Supply Labour to Lay New 600x600mm Floor Tiles, Wall Tiles and Subway Wall Tiles at Master Bathroom (*Not Including Tiles)\nc/w 3 Layers QuicSeal 104 Waterproofing", "desc2": "", "qty": 1, "unit": "JOB", "rate": 15500, "cost": 0, "amount": 15500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s1_4", "no": "41", "desc": "To Supply Labour to Lay New 600x600mm Floor Tiles, Wall Tiles and Subway Wall Tiles at Bathroom 2 (*Not Including Tiles)\nc/w 3 Layers QuicSeal 104 Waterproofing", "desc2": "", "qty": 1, "unit": "JOB", "rate": 16400, "cost": 0, "amount": 16400, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s2", "title": "Plumbing Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s2_0", "no": "42", "desc": "To Supply Labour and Fitting to Relocate Water Meter at Entrance", "desc2": "", "qty": 1, "unit": "JOB", "rate": 820, "cost": 0, "amount": 820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_1", "no": "43", "desc": "To Supply and Install Inlet and Outlet Water Piping for Water Tap at Car Porch", "desc2": "", "qty": 3, "unit": "JOB", "rate": 350, "cost": 0, "amount": 1050, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_2", "no": "44", "desc": "To Supply and Install Inlet and Outlet Water Piping for Dish Washer at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 820, "cost": 0, "amount": 820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_3", "no": "45", "desc": "To Supply and Install Inlet and Outlet Water Piping for Sink at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 820, "cost": 0, "amount": 820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_4", "no": "46", "desc": "To Supply and Install Inlet and Outlet Water Piping for Water Filter at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 820, "cost": 0, "amount": 820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_5", "no": "47", "desc": "To Supply and Install Inlet and Outlet Water Piping for Basin, Bidet, Toilet Bowl and Shower at Bathroom 4", "desc2": "", "qty": 1, "unit": "JOB", "rate": 5300, "cost": 0, "amount": 5300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_6", "no": "48", "desc": "To Supply Labour and Relocate Water Pipe at Yard", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1650, "cost": 0, "amount": 1650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_7", "no": "49", "desc": "To Supply and Install Inlet and Outlet Water Piping for Sink at Yard", "desc2": "", "qty": 1, "unit": "JOB", "rate": 820, "cost": 0, "amount": 820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_8", "no": "50", "desc": "To Supply and Install Inlet and Outlet Water Piping for Washing Machine at Yard", "desc2": "", "qty": 1, "unit": "JOB", "rate": 820, "cost": 0, "amount": 820, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_9", "no": "51", "desc": "To Supply and Install Inlet and Outlet Water Piping for Water Tap at Master Bedroom Balcony", "desc2": "", "qty": 1, "unit": "JOB", "rate": 940, "cost": 0, "amount": 940, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_10", "no": "52", "desc": "To Supply and Install Water Outlet Piping at Master Bedroom Balcony", "desc2": "", "qty": 1, "unit": "JOB", "rate": 590, "cost": 0, "amount": 590, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_11", "no": "53", "desc": "To Supply Labour to Relocate Inlet and Outlet Water Piping for Basin, Toilet Bowl and Shower at Master Bathroom\n*Including Install PPR Hot and Cold Inlet and Outlet Water Piping for Wash Basin and Shower", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4700, "cost": 0, "amount": 4700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s2_12", "no": "54", "desc": "To Supply Labour to Relocate Inlet and Outlet Water Piping for Basin, Bidet, Toilet Bowl and Shower at Bathroom 2\n*Including Install PPR Hot and Cold Inlet and Outlet Water Piping for Shower", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4700, "cost": 0, "amount": 4700, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s3", "title": "M&E Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s3_0", "no": "55", "desc": "Eyeball/Downlight/Surface Lighting Point", "desc2": "", "qty": 90, "unit": "NOS", "rate": 85, "cost": 0, "amount": 7650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_1", "no": "56", "desc": "To Supply Armoured Cable Lighting Point for Outdoor", "desc2": "", "qty": 18, "unit": "NOS", "rate": 170, "cost": 0, "amount": 3060, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_2", "no": "57", "desc": "LED Light Point", "desc2": "", "qty": 14, "unit": "NOS", "rate": 40, "cost": 0, "amount": 560, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_3", "no": "58", "desc": "13 Amp Power Socket Point", "desc2": "", "qty": 40, "unit": "NOS", "rate": 150, "cost": 0, "amount": 6000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_4", "no": "59", "desc": "13 Amp c/w Cover", "desc2": "", "qty": 2, "unit": "NOS", "rate": 200, "cost": 0, "amount": 400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_5", "no": "60", "desc": "15 Amp Power Socket Point", "desc2": "", "qty": 2, "unit": "NOS", "rate": 290, "cost": 0, "amount": 580, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_6", "no": "61", "desc": "20 Amp Power Socket Point (2.5mm)", "desc2": "", "qty": 6, "unit": "NOS", "rate": 330, "cost": 0, "amount": 1980, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_7", "no": "62", "desc": "2 Way Switch / 2 Way Light Point", "desc2": "", "qty": 2, "unit": "NOS", "rate": 170, "cost": 0, "amount": 340, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_8", "no": "63", "desc": "Aircon Point", "desc2": "", "qty": 5, "unit": "NOS", "rate": 330, "cost": 0, "amount": 1650, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_9", "no": "64", "desc": "Fan Point c/w Hook", "desc2": "", "qty": 6, "unit": "NOS", "rate": 130, "cost": 0, "amount": 780, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_10", "no": "65", "desc": "Hood Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 290, "cost": 0, "amount": 290, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_11", "no": "66", "desc": "Hob Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 290, "cost": 0, "amount": 290, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_12", "no": "67", "desc": "Oven Point", "desc2": "", "qty": 1, "unit": "NOS", "rate": 290, "cost": 0, "amount": 290, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_13", "no": "68", "desc": "Exhaust Fan Point", "desc2": "", "qty": 3, "unit": "NOS", "rate": 85, "cost": 0, "amount": 255, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_14", "no": "69", "desc": "Light Install", "desc2": "", "qty": 82, "unit": "NOS", "rate": 20, "cost": 0, "amount": 1640, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_15", "no": "70", "desc": "Track Light Install", "desc2": "", "qty": 17, "unit": "NOS", "rate": 65, "cost": 0, "amount": 1105, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_16", "no": "71", "desc": "LED Install", "desc2": "", "qty": 14, "unit": "NOS", "rate": 30, "cost": 0, "amount": 420, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_17", "no": "72", "desc": "Pendant Light Install", "desc2": "", "qty": 2, "unit": "NOS", "rate": 55, "cost": 0, "amount": 110, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_18", "no": "73", "desc": "Fan Install", "desc2": "", "qty": 6, "unit": "NOS", "rate": 55, "cost": 0, "amount": 330, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_19", "no": "74", "desc": "Exhaust Fan Install", "desc2": "", "qty": 3, "unit": "NOS", "rate": 55, "cost": 0, "amount": 165, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_20", "no": "75", "desc": "CCTV Install", "desc2": "", "qty": 6, "unit": "NOS", "rate": 55, "cost": 0, "amount": 330, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_21", "no": "76", "desc": "Autogate Point", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2400, "cost": 0, "amount": 2400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_22", "no": "77", "desc": "To Supply and Install GI Pipe at Family Hall and Master Bedroom", "desc2": "", "qty": 1, "unit": "NOS", "rate": 200, "cost": 0, "amount": 200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_23", "no": "78", "desc": "To Supply and Install PVC Pipe to Extend Dancing Area and Kitchen", "desc2": "", "qty": 2, "unit": "NOS", "rate": 660, "cost": 0, "amount": 1320, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s3_24", "no": "79", "desc": "Overall Hacking Slab and Skim Slab", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1000, "cost": 0, "amount": 1000, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s4", "title": "Air Conditioning Piping Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s4_0", "no": "80", "desc": "To Supply and Install New 1.5hp AC Copper Refrigerant Piping at Living, Study Room and Master Bedroom", "desc2": "", "qty": 3, "unit": "JOB", "rate": 1270, "cost": 0, "amount": 3810, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_1", "no": "81", "desc": "To Supply and Install New 1.5hp AC Copper Refrigerant Piping at Dancing Room and Guest Room", "desc2": "", "qty": 2, "unit": "JOB", "rate": 1000, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_2", "no": "82", "desc": "To Supply and Install 2.5hp Extra AC Copper Refrigerant Piping\nDimension : 98ft", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3160, "cost": 0, "amount": 3160, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_3", "no": "83", "desc": "To Supply and Install 3.0hp Extra AC Copper Refrigerant Piping at Kitchen", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2350, "cost": 0, "amount": 2350, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_4", "no": "84", "desc": "To Supply and Install 1.5hp Extra AC Copper Refrigerant Piping\nDimension : 56ft", "desc2": "", "qty": 1, "unit": "LS", "rate": 1570, "cost": 0, "amount": 1570, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_5", "no": "85", "desc": "To Supply Labour and Fitting to Install 1.0-1.5hp Wall-mounted AC at Dancing Room and Guest Room", "desc2": "", "qty": 2, "unit": "NOS", "rate": 400, "cost": 0, "amount": 800, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_6", "no": "86", "desc": "To Supply Labour and Fitting to Install 2.0-2.5hp Wall-mounted AC at Living, Study Room and Master Bedroom", "desc2": "", "qty": 3, "unit": "NOS", "rate": 530, "cost": 0, "amount": 1590, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s4_7", "no": "87", "desc": "To Supply Labour and Fitting to Install 3.0hp Cassette AC at Kitchen", "desc2": "", "qty": 1, "unit": "NOS", "rate": 800, "cost": 0, "amount": 800, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s5", "title": "Plaster Ceiling & Partition Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s5_0", "no": "88", "desc": "Plain Plaster Ceiling (Ground Floor)", "desc2": "", "qty": 400, "unit": "SQFT", "rate": 5.0, "cost": 0, "amount": 2000.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s5_1", "no": "89", "desc": "Manhole 18\"", "desc2": "", "qty": 2, "unit": "NOS", "rate": 120, "cost": 0, "amount": 240, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s5_2", "no": "90", "desc": "Plaster Ceiling L Box (Ground Floor)", "desc2": "", "qty": 10, "unit": "FT", "rate": 22, "cost": 0, "amount": 220, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s5_3", "no": "91", "desc": "Plaster Ceiling Light Holder (Ground Floor)", "desc2": "", "qty": 10, "unit": "FT", "rate": 23, "cost": 0, "amount": 230, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s5_4", "no": "92", "desc": "Plain Plaster Ceiling (First Floor)", "desc2": "", "qty": 200, "unit": "SQFT", "rate": 5.0, "cost": 0, "amount": 1000.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s5_5", "no": "93", "desc": "Plaster Ceiling L Box (First Floor)", "desc2": "", "qty": 10, "unit": "FT", "rate": 22, "cost": 0, "amount": 220, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s5_6", "no": "94", "desc": "Plaster Ceiling Light Holder (First Floor)", "desc2": "", "qty": 10, "unit": "FT", "rate": 23, "cost": 0, "amount": 230, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s6", "title": "Aluminium and Glass Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s6_0", "no": "95", "desc": "Shower Screen Fixed Panel c/w 10mm Tempered Clear Glass at Bathroom 4\nDimension : W800 H2100", "desc2": "", "qty": 1, "unit": "SET", "rate": 1000, "cost": 0, "amount": 1000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_1", "no": "96", "desc": "Standard Sliding Door c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Dancing Room\nDimension: W4350 H3110 (Required to make in 4 Panels + Lattice Design)", "desc2": "", "qty": 1, "unit": "SET", "rate": 9750, "cost": 0, "amount": 9750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_2", "no": "97", "desc": "Standard Casement Window c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Dancing Room\nDimension: W3600 H1500 (Max 6 Panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 3400, "cost": 0, "amount": 3400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_3", "no": "98", "desc": "Standard Casement Window c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Living\nDimension: W600 H2900", "desc2": "", "qty": 1, "unit": "SET", "rate": 1870, "cost": 0, "amount": 1870, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_4", "no": "99", "desc": "High Performance Folding Window (Hinges Exposed) c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Living\nDimension: W2800 H2400 (In 6 Panels + 1\" Flatbar Lattice Design)", "desc2": "", "qty": 1, "unit": "SET", "rate": 11400, "cost": 0, "amount": 11400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_5", "no": "100", "desc": "Standard Sliding Glass Door c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Kitchen\nDimension: W5520 H3110", "desc2": "", "qty": 1, "unit": "SET", "rate": 12880, "cost": 0, "amount": 12880, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_6", "no": "101", "desc": "Standard Sliding Door c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Kitchen\nDimension: W4650 H3110 (Required to make in 4 Panels + Lattice Design)", "desc2": "", "qty": 1, "unit": "SET", "rate": 10400, "cost": 0, "amount": 10400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_7", "no": "102", "desc": "High Performance Casement Door c/w 9.52mm Laminated Tempered and Frosted PVB and Aluminium Frame in p/c Black Finish at Yard\nDimension : W1000 H2100 (Max 1 Panel)", "desc2": "", "qty": 1, "unit": "SET", "rate": 4100, "cost": 0, "amount": 4100, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_8", "no": "103", "desc": "Slim Line Top Track Sliding Door with Hollow + U Channel c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Study Room", "desc2": "", "qty": 1, "unit": "SET", "rate": 9280, "cost": 0, "amount": 9280, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_9", "no": "104", "desc": "Standard Casement Window c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Study Room\nDimension : W2940 H2400 (Max 5 Panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 6200, "cost": 0, "amount": 6200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_10", "no": "105", "desc": "Standard Casement Window c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Study Room\nDimension : W1740 H2400 (Max 3 Panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 3750, "cost": 0, "amount": 3750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_11", "no": "106", "desc": "Standard Casement Window c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Master Bedroom\nDimension : W1650 H2400 (Max 2 Panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 3550, "cost": 0, "amount": 3550, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_12", "no": "107", "desc": "Standard Sliding Glass Door c/w 6mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Master Bedroom\nDimension : W3830 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 7000, "cost": 0, "amount": 7000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_13", "no": "108", "desc": "Standard Casement Window c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Master Bathroom\nDimension : W1365 H2025 (Max 2 Panels)", "desc2": "", "qty": 1, "unit": "SET", "rate": 2600, "cost": 0, "amount": 2600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s6_14", "no": "109", "desc": "Shower Screen with Swing Door c/w 10mm Tempered Clear Glass at Bathroom 2\nDimension : Swing Door - W700 H2100 / Fixed Glass Panel - W450 H2100", "desc2": "", "qty": 1, "unit": "SET", "rate": 1800, "cost": 0, "amount": 1800, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s7", "title": "Flooring Work (SPC, Vinyl and Laminate)", "optional": false, "items": [{"type": "item", "id": "qt264r3_s7_0", "no": "110", "desc": "To Supply and Install 5.5mm Vinyl Click System Flooring including Necessary Skirting, Beading and L Profile at Dancing Room", "desc2": "", "qty": 198, "unit": "SQFT", "rate": 11, "cost": 0, "amount": 2178, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s7_1", "no": "111", "desc": "To Supply and Install 5.5mm Vinyl Click System Flooring including Necessary Skirting, Beading and L Profile at Master Bedroom", "desc2": "", "qty": 383, "unit": "SQFT", "rate": 11, "cost": 0, "amount": 4213, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s7_2", "no": "112", "desc": "To Supply and Install SPC Staircase with Round Nosing at Staircase Area", "desc2": "", "qty": 19, "unit": "PIECES", "rate": 240, "cost": 0, "amount": 4560, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s7_3", "no": "113", "desc": "To Supply Material and Releveling Floor", "desc2": "", "qty": 581, "unit": "SQFT", "rate": 4.5, "cost": 0, "amount": 2614.5, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s8", "title": "Metal Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s8_0", "no": "114", "desc": "To Supply and Install Wood Deck Awning at Car Porch\nDimension : 6570mm x 1500mm, 4765mm x 1500mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 14700, "cost": 0, "amount": 14700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_1", "no": "115", "desc": "To Supply and Install Wood Deck Awning at Garden\nDimension : 5085mm x 1500mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 5600, "cost": 0, "amount": 5600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_2", "no": "116", "desc": "To Supply and Install Steel Door and Window at Foyer\nDimension : W1655 H3000", "desc2": "", "qty": 1, "unit": "SET", "rate": 9300, "cost": 0, "amount": 9300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_3", "no": "117", "desc": "To Supply and Install Mesh Sliding Door\nDimension : W1135 H900", "desc2": "", "qty": 1, "unit": "SET", "rate": 2000, "cost": 0, "amount": 2000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_4", "no": "118", "desc": "To Supply and Install Black Steel DB Box Cover\nDimension : W1305 D200 H800", "desc2": "", "qty": 2, "unit": "SET", "rate": 930, "cost": 0, "amount": 1860, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_5", "no": "119", "desc": "To Supply and Install Mesh Staircase Handrail\nDimension : W2530 H1000", "desc2": "", "qty": 1, "unit": "SET", "rate": 3750, "cost": 0, "amount": 3750, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_6", "no": "120", "desc": "To Supply and Install Mesh Staircase Railing\nDimension : W4880 H1000", "desc2": "", "qty": 1, "unit": "SET", "rate": 8000, "cost": 0, "amount": 8000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_7", "no": "121", "desc": "To Supply and Install Steel Rotate Door\nDimension : W1570 H3110, W2515 H3110", "desc2": "", "qty": 1, "unit": "SET", "rate": 16400, "cost": 0, "amount": 16400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_8", "no": "122", "desc": "To Supply and Install Steel Pivot Door\nDimension : W1940 H3110", "desc2": "", "qty": 1, "unit": "SET", "rate": 7200, "cost": 0, "amount": 7200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_9", "no": "123", "desc": "To Supply and Install Stainless Steel Backsplash at Kitchen\nDimension : 1800mm x 1800mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 5200, "cost": 0, "amount": 5200, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_10", "no": "124", "desc": "To Supply and Install Steel I Beam at Kitchen\nDimension : W4500 H300", "desc2": "", "qty": 1, "unit": "SET", "rate": 5300, "cost": 0, "amount": 5300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_11", "no": "125", "desc": "To Supply and Install Skylight Awning at Kitchen\nDimension : 2400mm x 3812mm", "desc2": "", "qty": 1, "unit": "SET", "rate": 8000, "cost": 0, "amount": 8000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_12", "no": "126", "desc": "To Supply and Install Skylight Awning at Study Room\nDimension : 750mm x 1500mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1600, "cost": 0, "amount": 1600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_13", "no": "127", "desc": "To Supply Labour to Modify Existing Gutter at Master Bedroom Balcony", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2670, "cost": 0, "amount": 2670, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_14", "no": "128", "desc": "To Supply and Install Steel I Beam at Master Bedroom Balcony\nDimension : W6205 H250 *2", "desc2": "", "qty": 1, "unit": "JOB", "rate": 6150, "cost": 0, "amount": 6150, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s8_15", "no": "129", "desc": "To Supply and Install Skylight Awning at Master Bathroom\nDimension : 1565mm x 1415mm", "desc2": "", "qty": 1, "unit": "JOB", "rate": 2400, "cost": 0, "amount": 2400, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s9", "title": "Painting & Touch Up Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s9_0", "no": "130", "desc": "To Supply Labour and Material\n- To Clean Off Existing Exterior Wall Stain with Water Jet for Exterior Stain\n- Exterior Wall - Jotun Ultra Clean Series/Nippon Weatherbond Series (3 Color)\n- Interior Wall - Jotun Majestic Series / Nippon Easywash Series (3 Color)\n- Door, Door Frame, Ceiling, Staircase Railing Included", "desc2": "", "qty": 1, "unit": "JOB", "rate": 23730, "cost": 0, "amount": 23730, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s9_1", "no": "131", "desc": "To Supply Labour and Material to Skim Coat at Facade Planter Box and Staircase Area", "desc2": "", "qty": 560, "unit": "SQFT", "rate": 16, "cost": 0, "amount": 8960, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s10", "title": "Carpentry Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s10_0", "no": "132", "desc": "Base Cabinet c/w Solid Plywood In Selected Laminated Finish at Kitchen\nDimension : Base Cabinet - W3300 D750 H900 / Stainless Steel Table Top - W3300 D750 H900", "desc2": "", "qty": 2, "unit": "SET", "rate": 10425, "cost": 0, "amount": 20850, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_1", "no": "133", "desc": "Shelving c/w Solid Plywood In Selected Laminated Finish at Bathroom 4\nDimension : Shelving - W750 D200 H40 / Sintered Stone Table Top - W930 D600", "desc2": "", "qty": 1, "unit": "SET", "rate": 2400, "cost": 0, "amount": 2400, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_2", "no": "134", "desc": "Sliding Wardrobe c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Wardrobe Door and Door Frame - W3600 D650 H3180 - c/w Sliding Track", "desc2": "", "qty": 1, "unit": "SET", "rate": 20000, "cost": 0, "amount": 20000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_3", "no": "135", "desc": "Platform, Bedhead and Bedside Shelving c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Platform - 58sqft / Bedhead - W3450 H800 / Bedside Shelving - W700+650 D450 H100", "desc2": "", "qty": 1, "unit": "SET", "rate": 8900, "cost": 0, "amount": 8900, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_4", "no": "136", "desc": "Vanity Cabinet c/w Solid Plywood In Selected Laminated Finish at Master Bathroom\nDimension : Vanity Cabinet - W1350 D500 H300 / Sintered Stone Table Top - W1350 D500", "desc2": "", "qty": 1, "unit": "SET", "rate": 3600, "cost": 0, "amount": 3600, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_5", "no": "137", "desc": "Shelving c/w Solid Plywood In Selected Laminated Finish at Master Bathroom\nDimension : Shelving - 2ft", "desc2": "", "qty": 1, "unit": "SET", "rate": 500, "cost": 0, "amount": 500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_6", "no": "138", "desc": "Vanity Cabinet c/w Solid Plywood In Selected Laminated Finish at Bathroom 2\nDimension : Vanity Cabinet - W1600 D600 H405 / Sintered Stone Table Top - W1600 D600", "desc2": "", "qty": 1, "unit": "SET", "rate": 4300, "cost": 0, "amount": 4300, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s10_7", "no": "139", "desc": "Touch Up (Cabinet Edging Paint)", "desc2": "", "qty": 1, "unit": "SET", "rate": 2670, "cost": 0, "amount": 2670, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s11", "title": "Item Supply", "optional": false, "items": [{"type": "item", "id": "qt264r3_s11_0", "no": "140", "desc": "To Supply Ventilation Block", "desc2": "", "qty": 580, "unit": "PIECES", "rate": 9, "cost": 0, "amount": 5220, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s11_1", "no": "141", "desc": "To Supply and Install Steel Autogate, Steel Mailbox and Steel Door with 4inch Frame at Entrance\nDimension : Autogate - W5530 H1800 / Mailbox - W600 H1000 / Door - W1000 H1800", "desc2": "", "qty": 1, "unit": "SET", "rate": 19500, "cost": 0, "amount": 19500, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s12", "title": "Door and Door Frame", "optional": false, "items": [{"type": "item", "id": "qt264r3_s12_0", "no": "142", "desc": "To Supply and Install Plywood Semi Solid Door c/w Laminate Door Frame - Including Hinges and Mortics Lock\nDimension : W750 H2400", "desc2": "", "qty": 2, "unit": "SET", "rate": 3250, "cost": 0, "amount": 6500, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s13", "title": "Miscellaneous Work", "optional": false, "items": [{"type": "item", "id": "qt264r3_s13_0", "no": "143", "desc": "To Supply 4 Waste Bins to Clear Debris During Renovation Period", "desc2": "", "qty": 1, "unit": "JOB", "rate": 1000, "cost": 0, "amount": 1000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s13_1", "no": "144", "desc": "To Supply and Lay Floorgard Mat Floor Protection 1 Times During Renovation Period", "desc2": "", "qty": 1, "unit": "JOB", "rate": 3000, "cost": 0, "amount": 3000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s13_2", "no": "145", "desc": "To Supply Labour and Material to Clean The Entire Unit 2 Times (in the middle and the end of renovation period)", "desc2": "", "qty": 1, "unit": "JOB", "rate": 4000, "cost": 0, "amount": 4000, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s14", "title": "Discount", "optional": false, "items": [{"type": "item", "id": "qt264r3_s14_0", "no": "146", "desc": "Special Discount", "desc2": "", "qty": 1, "unit": "LS", "rate": -64910.5, "cost": 0, "amount": -64910.5, "foc": false, "focRate": 0}]}, {"id": "qt264r3_s15", "title": "Optional Item", "optional": true, "items": [{"type": "item", "id": "qt264r3_s15_0", "no": "1", "desc": "Standard Casement Window c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Living\nDimension: W600 H2900 (In 1 Panel + 1\" Flatbar Lattice Design)", "desc2": "", "qty": 1, "unit": "SET", "rate": 2240, "cost": 0, "amount": 2240, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_1", "no": "2", "desc": "Aluminium Framed Door c/w 6mm Tempered Clear Glass Using Spinning Accessories\nDimension : W2515 H3110, W1570 H3110", "desc2": "", "qty": 1, "unit": "SET", "rate": 25500, "cost": 0, "amount": 25500, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_2", "no": "3", "desc": "High Performance Folding Door (Hinges Exposed) c/w 8mm Tempered Clear Glass and Aluminium in p/c Black Finish at Kitchen\nDimension: W5520 H3110 (In 3L3R Opening Method + 1\" Flatbar Lattice Design)", "desc2": "", "qty": 1, "unit": "SET", "rate": 21700, "cost": 0, "amount": 21700, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_3", "no": "4", "desc": "High Performance Sliding Glass Door c/w 8mm Tempered Clear Glass and Aluminium Frame in p/c Black Finish at Master Bedroom\nDimension : W3830 H2700", "desc2": "", "qty": 1, "unit": "SET", "rate": 12000, "cost": 0, "amount": 12000, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_4", "no": "5", "desc": "To Supply and Install 12mm Engineered Timber Flooring at Dancing Room", "desc2": "", "qty": 198, "unit": "SQFT", "rate": 31.5, "cost": 0, "amount": 6237.0, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_5", "no": "6", "desc": "To Supply and Install 12mm Engineered Timber Flooring at Master Bedroom, Study Room and Guest Room", "desc2": "", "qty": 837, "unit": "SQFT", "rate": 31.5, "cost": 0, "amount": 26365.5, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_6", "no": "7", "desc": "To Supply and Install 12mm Engineered Timber Flooring at Staircase Area", "desc2": "", "qty": 19, "unit": "PIECES", "rate": 375, "cost": 0, "amount": 7125, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_7", "no": "8", "desc": "To Supply and Install Metal Clothes Rack at Guest Room\nDimension : W1299 H1410", "desc2": "", "qty": 1, "unit": "SET", "rate": 530, "cost": 0, "amount": 530, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_8", "no": "9", "desc": "To Supply Labour and Material - To Repair / Skim Coat the Walls and Sealer Application - Texture Painting Work for Exterior and Interior Wall and Ceiling", "desc2": "", "qty": 11883, "unit": "SQFT", "rate": 16, "cost": 0, "amount": 190128, "foc": false, "focRate": 0}, {"type": "item", "id": "qt264r3_s15_9", "no": "10", "desc": "Wardrobe c/w Solid Plywood In Selected Laminated Finish at Master Bedroom\nDimension : Wardrobe - W3600 D650 H3180", "desc2": "", "qty": 1, "unit": "SET", "rate": 13280, "cost": 0, "amount": 13280, "foc": false, "focRate": 0}]}], "pis": [], "payments": [], "invoices": []}; if(_ex){Object.assign(_ex,q);}else{_ql.push(q);} const _mi=QUOT_LIST.findIndex(qq=>qq.id===QID); if(_mi>=0){Object.assign(QUOT_LIST[_mi],q);}else{QUOT_LIST.push(q);} localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); console.log('[INZII] Migration v8: INZ-QUO-00264-R3 imported.'); })(); // โ”€โ”€ End migration v8 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v9: backfill payments for INZ-QUO-00204-R1 and INZ-QUO-00264-R3 โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v9'))return; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); let chg=false; const uid=()=>'m9'+Math.random().toString(36).slice(2,9); const pays=[ {qn:'INZ-QUO-00204-R1',rn:'INZ-R-00169',st:1,am:200000,dt:'2025-04-29',me:'Bank Transfer'}, {qn:'INZ-QUO-00204-R1',rn:'INZ-R-00185',st:1,am:288750,dt:'2025-07-07',me:'Bank Transfer'}, {qn:'INZ-QUO-00204-R1',rn:'INZ-R-00192',st:2,am:100000,dt:'2025-08-29',me:'Bank Transfer'}, {qn:'INZ-QUO-00204-R1',rn:'INZ-R-00194',st:2,am:30000, dt:'2025-09-16',me:'Bank Transfer'}, {qn:'INZ-QUO-00204-R1',rn:'INZ-R-00208',st:2,am:300000,dt:'2025-11-06',me:'Bank Transfer'}, {qn:'INZ-QUO-00204-R1',rn:'INZ-R-00257',st:2,am:385000,dt:'2026-02-14',me:'Bank Transfer'}, {qn:'INZ-QUO-00264-R3',rn:'INZ-R-00210',st:1,am:206100,dt:'2025-11-10',me:'Bank Transfer'}, ]; pays.forEach(p=>{ const q=_ql.find(x=>x.id===p.qn);if(!q)return; if(!q.payments)q.payments=[]; if(q.payments.some(x=>x.rcpNo===p.rn))return; q.payments.push({id:uid(),rcpNo:p.rn,stageNo:p.st,stageLabel:'Stage '+p.st, description:'Payment for '+p.qn,amount:p.am,date:p.dt,method:p.me, transactionNo:'',badDebt:false,bank:'',remarks:'', createdAt:new Date().toISOString()}); chg=true; }); if(chg){ // sync to QUOT_LIST pays.forEach(p=>{ const mi=QUOT_LIST.findIndex(x=>x.id===p.qn); const qs=_ql.find(x=>x.id===p.qn); if(mi>=0&&qs)QUOT_LIST[mi].payments=qs.payments; }); localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); } localStorage.setItem('inzii_mig_v9','1'); console.log('[INZII] Migration v9: payments backfilled.'); })(); // โ”€โ”€ End migration v9 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v10: split desc/desc2 for Q204 and Q264 โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v10'))return; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); let chg=false; ['INZ-QUO-00204-R1','INZ-QUO-00264-R3'].forEach(qid=>{ const q=_ql.find(x=>x.id===qid);if(!q)return; (q.sections||[]).forEach(sec=>{ (sec.items||[]).forEach(it=>{ if(it.type==='subhdr')return; const nl=it.desc.indexOf('\n'); if(nl<0)return; it.desc2=(it.desc.slice(nl+1)+(it.desc2?'\n'+it.desc2:'')).trim(); it.desc=it.desc.slice(0,nl).trim(); chg=true; }); }); if(chg){ const mi=QUOT_LIST.findIndex(x=>x.id===qid); if(mi>=0)Object.assign(QUOT_LIST[mi],q); } }); if(chg)localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); localStorage.setItem('inzii_mig_v10','1'); console.log('[INZII] Migration v10: desc/desc2 split done.'); })(); // โ”€โ”€ End migration v10 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v11: set projectCode PJ1091 for ZOCRAFT โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v11'))return; let cls=JSON.parse(localStorage.getItem('inzii_clients')||'[]'); const cl=cls.find(x=>x.id==='CL0103'||x.name==='ZOCRAFT SDN BHD'); if(cl&&!cl.projectCode){cl.projectCode='PJ1091';localStorage.setItem('inzii_clients',JSON.stringify(cls));} localStorage.setItem('inzii_mig_v11','1'); })(); // โ”€โ”€ End migration v11 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v12: import 2025 related-project transactions โ”€โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v12'))return; let _txns=JSON.parse(localStorage.getItem('inzii_acc_txns')||'[]'); const maxId=_txns.reduce((m,t)=>Math.max(m,parseInt(t.id?.replace('AT','')||0)),0); let nextId=maxId+1; const _id=()=>'AT'+String(nextId++).padStart(4,'0'); const _now=new Date().toISOString(); const newTxns=[ // โ”€โ”€ OUT โ”€โ”€ {id:_id(),type:'out',category:'Project Expense',projectCode:'PJ1078',submittedDate:'2025-12-30',payeeName:'HANER EAN PROTECT SDN BHD',bankName:'PUBLIC BANK BHD',bankAccount:'3241211328',billNo:'IV-01041',submittedAmount:577,workDescription:'MISCELLANEOUS WORK',remarks:'',approvedDate:'2025-12-31',projectSplits:[],createdAt:_now}, {id:_id(),type:'out',category:'Project Expense',projectCode:'PJ1069',submittedDate:'2025-08-01',payeeName:'LIM HONG MIN',bankName:'PUBLIC BANK BHD',bankAccount:'5008984729',billNo:'',submittedAmount:11,workDescription:'OTHERS',remarks:'DUPLICATE KEY',approvedDate:'2025-08-02',projectSplits:[],createdAt:_now}, {id:_id(),type:'out',category:'Project Expense',projectCode:'PJ1069',submittedDate:'2025-09-01',payeeName:'LIM HONG MIN',bankName:'PUBLIC BANK BHD',bankAccount:'5008984729',billNo:'',submittedAmount:11,workDescription:'OTHERS',remarks:'DELIVERY KEY',approvedDate:'2025-09-02',projectSplits:[],createdAt:_now}, {id:_id(),type:'out',category:'Project Expense',projectCode:'PJ1069',submittedDate:'2025-09-22',payeeName:'POH ZI YANG',bankName:'CIMB BANK',bankAccount:'7609224113',billNo:'NO. 091',submittedAmount:600,workDescription:'OTHERS',remarks:'CHECK DEFECT',approvedDate:'2025-09-26',projectSplits:[],createdAt:_now}, // โ”€โ”€ IN โ”€โ”€ {id:_id(),type:'in',category:'Design Income',projectCode:'PJ1078',receivedDate:'2025-10-28',amountReceived:4750,workDescription:'DESIGN DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Construction Income',projectCode:'PJ1078',receivedDate:'2025-12-29',amountReceived:50000,workDescription:'CONSTRUCTION DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Construction Income',projectCode:'PJ1078',receivedDate:'2025-12-30',amountReceived:48800,workDescription:'CONSTRUCTION DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Design Income',projectCode:'PJ1077',receivedDate:'2025-09-22',amountReceived:4750,workDescription:'DESIGN DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Construction Income',projectCode:'PJ1077',receivedDate:'2025-12-24',amountReceived:103200,workDescription:'CONSTRUCTION DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Design Income',projectCode:'PJ1079',receivedDate:'2025-11-24',amountReceived:4250,workDescription:'DESIGN DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Design Income',projectCode:'PJ1080',receivedDate:'2025-12-11',amountReceived:7500,workDescription:'DESIGN DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Design Income',projectCode:'PJ1069',receivedDate:'2025-03-14',amountReceived:6750,workDescription:'DESIGN DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Construction Income',projectCode:'PJ1069',receivedDate:'2025-11-10',amountReceived:206100,workDescription:'CONSTRUCTION DEPOSIT',remarks:'',projectSplits:[],createdAt:_now}, {id:_id(),type:'in',category:'Design Income',projectCode:'PJ1069',receivedDate:'2025-11-30',amountReceived:5400,workDescription:'DESIGN BALANCE',remarks:'',projectSplits:[],createdAt:_now}, ]; _txns=_txns.concat(newTxns); localStorage.setItem('inzii_acc_txns',JSON.stringify(_txns)); localStorage.setItem('inzii_mig_v12','1'); console.log('[INZII] Migration v12: imported 14 transactions (2025 related projects)'); })(); // โ”€โ”€ End migration v12 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration v6: manual payment-to-invoice corrections โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_v6'))return; // Corrections: cross-quotation linkedPayments where auto-match can't resolve const corrections=[ // [quotId, invNo, linkedPayments[], status] ['INZ-QUO-ZOCRAFT','INZ-INV-00078',['INZ-R-00224'],'Completed'], ['INZ-QUO-ZOCRAFT','INZ-INV-00044',['INZ-R-00126'],'Completed'], ]; corrections.forEach(([qid,invNo,linked,status])=>{ const q=QUOT_LIST.find(x=>x.id===qid);if(!q)return; if(!q.invoices)q.invoices=[]; const inv=q.invoices.find(x=>x.invNo===invNo); if(inv){inv.linkedPayments=linked;inv.status=status;} }); localStorage.setItem('inzii_quotations',JSON.stringify(QUOT_LIST)); localStorage.setItem('inzii_mig_v6','1'); console.log('[INZII] Migration v6: invoice payment corrections applied.'); })(); // โ”€โ”€ End migration v6 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Migration: fix duplicate / missing PI ids โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function(){ if(localStorage.getItem('inzii_mig_pifix2'))return; let _ql=JSON.parse(localStorage.getItem('inzii_quotations')||'[]'); const seenIds=new Set(); let changed=false; _ql.forEach(q=>{ (q.pis||[]).forEach(p=>{ if(!p.id||seenIds.has(p.id)){ p.id='pi-'+Date.now()+'-'+Math.random().toString(36).slice(2,6); changed=true; } seenIds.add(p.id); }); }); if(changed)localStorage.setItem('inzii_quotations',JSON.stringify(_ql)); localStorage.setItem('inzii_mig_pifix2','1'); })(); // โ”€โ”€ End migration: fix PI ids โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // Ensure counters never go below minimum starting values (function(){ const _ensure=(k,min)=>{if(+(localStorage.getItem(k)||0){ const file=e.target.files[0];if(!file)return; const ab=await file.arrayBuffer(); const wb=XLSX.read(ab,{type:'array'}); const ws=wb.Sheets['Quotations']; if(!ws){toast('โŒ ๆ‰พไธๅˆฐ "Quotations" sheet');return;} const rows=XLSX.utils.sheet_to_json(ws,{header:1,raw:true}); let added=0,skipped=0; for(let i=4;iq.id===id)){skipped++;continue;} const finalAmt=parseFloat(r[9])||0; QUOT_LIST.push({ id,quotNo,revision:rev, client:r[2]||'',clientPhone:r[3]||'', date:_xlDate(r[4])||new Date().toISOString().slice(0,10), handler:r[5]||'',status:r[6]||'In Progress', wonDeal:_xlDate(r[7]),remarks:r[8]||'', finalAmt,totalAmt:finalAmt, totalDisc:parseFloat(r[10])||0,taxAmt:parseFloat(r[11])||0, paymentTerm:r[12]||'Design and Renovation (40%, 30%, 20%, 10%)', tag:r[13]||'',termCondition:'Terms & Conditions - Construction Use', designAgreement:'',sections:[],pis:[],invoices:[],payments:[], createdAt:new Date().toISOString(),updatedAt:new Date().toISOString() }); added++; } // Line items sheet const ws2=wb.Sheets['Line Items (Optional)']; if(ws2){ const liRows=XLSX.utils.sheet_to_json(ws2,{header:1,raw:true}); for(let i=4;ix.quotNo===qn).slice(-1)[0]; if(!q)continue; const secName=r[1]||'Items'; let sec=q.sections.find(s=>s.name===secName); if(!sec){sec={name:secName,items:[]};q.sections.push(sec);} const qty=parseFloat(r[4])||1,up=parseFloat(r[5])||0; sec.items.push({desc:r[2]||'',unit:r[3]||'lot',qty,unitPrice:up,amount:qty*up,remark:r[7]||''}); } } saveQuotations();renderQuotations(); toast(`โœ… ๅทฒๅŒฏๅ…ฅ ${added} ไปฝ Quotation${skipped?'๏ผŒ่ทณ้Ž '+skipped+' ไปฝ๏ผˆๅทฒๅญ˜ๅœจ๏ผ‰':''}`); }; inp.click(); } // โ”€โ”€ Shared: Parse single quotation Excel file โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function _parseQuotXlsx(rows){ const kv={}; for(let i=0;i<12;i++){ const r=rows[i];if(!r||!r[0])continue; kv[String(r[0]).trim().toLowerCase()]=r[1]!==undefined?r[1]:''; } // Find header row โ€” try 3 strategies let hdr=-1; // Strategy 1: look for 'Section' + 'Item' in first 20 rows for(let i=0;i10)hdr=9; if(hdr===-1)return null; console.log('[Inzii Import] Header row found at index',hdr,'โ†’',JSON.stringify(rows[hdr])); // โ”€โ”€ Dynamic column detection from header row โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const hdrRow=(rows[hdr]||[]).map(h=>String(h||'').toLowerCase().replace(/[^a-z0-9]/g,'')); const _ci=(...kwds)=>{ for(const kw of kwds){ const k=kw.toLowerCase().replace(/[^a-z0-9]/g,''); // 1. Exact match let i=hdrRow.findIndex(h=>h===k);if(i!==-1)return i; // 2. Starts-with match i=hdrRow.findIndex(h=>h.startsWith(k));if(i!==-1)return i; // 3. Contains match i=hdrRow.findIndex(h=>h.includes(k));if(i!==-1)return i; } return -1; }; const CI_SEC =_ci('section'); const CI_NO =_ci('itemno','no'); const CI_SUBSEC=_ci('subsection','subsec'); const CI_DESC =_ci('itemname','description'); const CI_DESC2 =_ci('itemdescription','detailsdimension','details','dimension','spec'); const CI_QTY =_ci('qty','quantity'); const CI_UNIT =_ci('unit'); const CI_RATE =_ci('unitrate','rate'); const CI_AMT =_ci('amount'); const CI_COST =_ci('estcost','estcostmyr','cost'); const CI_FOC =_ci('foc'); // Ensure UNIT doesn't collapse onto UNIT RATE column const CI_UNIT_SAFE=(CI_UNIT===CI_RATE)?CI_UNIT-1:CI_UNIT; console.log('[Inzii Import] Columns detected:',{CI_SEC,CI_NO,CI_SUBSEC,CI_DESC,CI_DESC2,CI_QTY,CI_UNIT:CI_UNIT_SAFE,CI_RATE,CI_AMT,CI_COST,CI_FOC}); const _s=(r,ci,fb)=>String(ci>=0?(r[ci]??''):(r[fb]??'')).trim(); const _n=(r,ci,fb)=>parseFloat(ci>=0?(r[ci]??0):(r[fb]??0))||0; const uid=()=>'i'+(Date.now()+Math.random()).toString(36).replace('.',''); const sections=[]; let curSec=null; let curSecName=''; let total=0; let itemNo=0; for(let i=hdr+1;i=0?r[CI_NO]:r[1]; const subSec =_s(r,CI_SUBSEC,-1); // sub-section text (template only) const desc =_s(r,CI_DESC,2); // ITEM NAME const desc2 =_s(r,CI_DESC2,3); // Details/Dimension const qty =_n(r,CI_QTY,4); const unit =_s(r,CI_UNIT_SAFE,5)||'JOB'; const rate =_n(r,CI_RATE,6); const amount =_n(r,CI_AMT,7); const cost =_n(r,CI_COST,8); const focRaw =CI_FOC>=0?String(r[CI_FOC]||'').trim().toUpperCase():''; const isFoc =focRaw==='YES'||focRaw==='Y'||focRaw==='TRUE'; // Stop at payment terms if(secName.toLowerCase().includes('payment term'))break; if(!secName&&!iNo&&!desc&&!subSec&&amount===0)continue; // New section if(secName&&secName!==curSecName){ curSecName=secName; curSec={id:uid(),title:secName,optional:secName.startsWith('[Optional]')||secName.startsWith('(Optional)'),items:[]}; sections.push(curSec); itemNo=0; } if(!curSec)continue; // Sub-header: template has dedicated Sub-Section col; original format uses desc with no iNo/amount const subHdrTitle=subSec||((!iNo&&desc&&amount===0&&qty===0)?desc:''); if(subHdrTitle&&!iNo&&amount===0&&qty===0){ curSec.items.push({type:'subhdr',id:uid(),title:subHdrTitle}); continue; } // Regular item if((iNo!==null&&iNo!==undefined&&iNo!=='')||amount>0){ itemNo++; const item={type:'item',id:uid(),no:iNo||itemNo, desc,desc2, qty:qty||1,unit,rate:rate||amount, cost,amount,foc:isFoc,focRate:0}; curSec.items.push(item); if(!isFoc)total+=amount; } } // Parse date const rawDate=kv['date']||''; const quotDate=typeof rawDate==='string'?rawDate.slice(0,10):_xlDate(rawDate); const statusMap={'won':'Won','in progress':'In Progress','pending':'In Progress','lost':'Lost','cancelled':'Cancelled'}; const status=statusMap[String(kv['status']||'').toLowerCase()]||kv['status']||'In Progress'; return{ id:String(kv['quotation no.']||kv['quotation no']||'').trim(), client:String(kv['client']||'').trim(), clientPhone:String(kv['contact']||kv['contact no.']||kv['contact no']||'').trim(), address:String(kv['address']||'').trim(), date:quotDate, handler:String(kv['handler']||kv['designer']||'').trim(), status, remarks:String(kv['project / remarks']||kv['project/remarks']||kv['remarks']||'').trim(), tag:String(kv['type']||'').trim(), sections, total:parseFloat(total.toFixed(2)) }; } // โ”€โ”€ Import Excel into current Quotation Form โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ async function importQuotFileIntoForm(){ await _loadScript('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js'); const inp=document.createElement('input');inp.type='file';inp.accept='.xlsx,.xls'; inp.onchange=async e=>{ const file=e.target.files[0];if(!file)return; const ab=await file.arrayBuffer(); const wb=XLSX.read(ab,{type:'array',cellDates:true}); const ws=wb.Sheets[wb.SheetNames[0]]; if(!ws){toast('โŒ ็„กๆณ•่ฎ€ๅ– Excel');return;} const rows=XLSX.utils.sheet_to_json(ws,{header:1,raw:true}); let d; try{d=_parseQuotXlsx(rows);}catch(err){toast('โŒ ่งฃๆžๅคฑๆ•—๏ผš'+err.message);console.error(err);return;} if(!d){toast('โŒ ๆ‰พไธๅˆฐ Section/Item ๆจ™้กŒ่กŒ');return;} // Fill form fields const _sv=(id,val)=>{const el=document.getElementById(id);if(el&&val)el.value=val;}; _sv('qtf_client',d.client); _sv('qtf_phone',d.clientPhone); _sv('qtf_remarks',d.remarks); _sv('qtf_date',d.date); _sv('qtf_handler',d.handler); _sv('qtf_tag',d.tag); if(d.status){const sel=document.getElementById('qtf_status');if(sel)sel.value=d.status;} // Sync to _qtForm if(d.client)_qtForm.client=d.client; if(d.clientPhone)_qtForm.clientPhone=d.clientPhone; if(d.remarks)_qtForm.remarks=d.remarks; if(d.date)_qtForm.date=d.date; if(d.handler)_qtForm.handler=d.handler; if(d.tag)_qtForm.tag=d.tag; if(d.status)_qtForm.status=d.status; _qtForm.sections=d.sections; _qtForm.finalAmt=d.total; qtRenderSections(); qtCalcTotals(); toast('โœ… ๅทฒ่ผ‰ๅ…ฅ๏ผˆ'+d.sections.length+' sections๏ผŒRM '+fmt(d.total)+'๏ผ‰โ€” ่ซ‹่จ˜ๅพ— Save'); }; inp.click(); } // โ”€โ”€ Excel Import: Single Quotation File โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ async function importSingleQuotExcel(){ await _loadScript('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js'); const inp=document.createElement('input');inp.type='file';inp.accept='.xlsx,.xls'; inp.onchange=async e=>{ const file=e.target.files[0];if(!file)return; const ab=await file.arrayBuffer(); const wb=XLSX.read(ab,{type:'array',cellDates:true}); const ws=wb.Sheets[wb.SheetNames[0]]; if(!ws){toast('โŒ ็„กๆณ•่ฎ€ๅ– Excel');return;} const rows=XLSX.utils.sheet_to_json(ws,{header:1,raw:true}); let d; try{d=_parseQuotXlsx(rows);}catch(err){toast('โŒ ่งฃๆžๅคฑๆ•—๏ผš'+err.message);console.error(err);return;} if(!d){toast('โŒ ๆ‰พไธๅˆฐ Section/Item ๆจ™้กŒ่กŒ');return;} if(!d.id){toast('โŒ ๆ‰พไธๅˆฐ Quotation No.');return;} const _existIdx=QUOT_LIST.findIndex(q=>q.id===d.id); const _isUpdate=_existIdx!==-1; if(_isUpdate&&!confirm(d.id+' ๅทฒๅญ˜ๅœจใ€‚\n\n้ปžๆ“Š OK ๆ›ดๆ–ฐ๏ผˆSections/Line Items/้‡‘้ก๏ผ‰๏ผŒ\nๅ–ๆถˆๅ‰‡ๆ”พๆฃ„ใ€‚')){return;} const quot={ id:d.id,quotNo:d.id.replace(/-R\d+$/,''),revision:0, client:d.client,clientPhone:d.clientPhone,address:d.address, date:d.date,handler:d.handler,status:d.status, wonDeal:d.status==='Won'?d.date:'', remarks:d.remarks,tag:d.tag, finalAmt:d.total,totalAmt:d.total,totalDisc:0,taxAmt:0, paymentTerm:'',termCondition:'Terms & Conditions - Construction Use', designAgreement:'',sections:d.sections, pis:[],invoices:[],payments:[], createdAt:new Date().toISOString(),updatedAt:new Date().toISOString() }; if(_isUpdate){ const _ex=QUOT_LIST[_existIdx]; Object.assign(_ex,{client:quot.client||_ex.client,clientPhone:quot.clientPhone||_ex.clientPhone, address:quot.address||_ex.address,date:quot.date||_ex.date,handler:quot.handler||_ex.handler, status:quot.status||_ex.status,remarks:quot.remarks||_ex.remarks,tag:quot.tag||_ex.tag, finalAmt:quot.finalAmt,totalAmt:quot.totalAmt,sections:quot.sections, updatedAt:new Date().toISOString()}); toast('โœ… ๅทฒๆ›ดๆ–ฐ '+d.id+'๏ผˆ'+d.sections.length+' sections๏ผŒRM '+fmt(d.total)+'๏ผ‰'); } else { QUOT_LIST.push(quot); toast('โœ… ๅทฒๅŒฏๅ…ฅ '+d.id+'๏ผˆ'+d.sections.length+' sections๏ผŒRM '+fmt(d.total)+'๏ผ‰'); } saveQuotations();renderQuotations(); }; inp.click(); } // โ”€โ”€ Excel Import: Payslip โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ async function importPayslipExcel(){ await _loadScript('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js'); const inp=document.createElement('input');inp.type='file';inp.accept='.xlsx,.xls'; inp.onchange=async e=>{ const file=e.target.files[0];if(!file)return; const ab=await file.arrayBuffer(); const wb=XLSX.read(ab,{type:'array'}); const ws=wb.Sheets['Payslips']; if(!ws){toast('โŒ ๆ‰พไธๅˆฐ "Payslips" sheet');return;} const rows=XLSX.utils.sheet_to_json(ws,{header:1,raw:true}); const MO=['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC']; let added=0,skipped=0; for(let i=5;ip.id===id)){skipped++;continue;} const earnings=[]; const bp=parseFloat(r[12])||0;if(bp)earnings.push({desc:'BASIC PAY',amount:bp}); if(r[13])earnings.push({desc:String(r[14]||'ALLOWANCE').toUpperCase(),amount:parseFloat(r[13])||0}); if(r[15])earnings.push({desc:String(r[16]||'ALLOWANCE').toUpperCase(),amount:parseFloat(r[15])||0}); if(r[17])earnings.push({desc:'COMMISSION',amount:parseFloat(r[17])||0,remark:r[18]||''}); const gross=earnings.reduce((s,x)=>s+x.amount,0); const epfE=parseFloat(r[19])||0,socsoE=parseFloat(r[20])||0,eisE=parseFloat(r[21])||0,tax=parseFloat(r[22])||0; const totDed=epfE+socsoE+eisE+tax; PS_LIST.push({ id,empNo,empName:String(r[1]||'').toUpperCase(), ic:r[2]||'',epfNo:r[3]||'',taxNo:r[4]||'', department:String(r[5]||'').toUpperCase(), empStatus:'ACTIVE',taxStatus:'NORMAL', periodLabel:period,periodShort, periodStart:pStart,periodEnd:_xlDate(r[8])||pStart, issueDate:_xlDate(r[9])||new Date().toISOString().slice(0,10), wdWorked:String(r[10]||''),wdTotal:String(r[11]||''), earnings, ded:{epf:epfE,socso:socsoE,eis:eisE,tax,unpaid:0}, emp:{epf:Math.round(gross*0.13*100)/100,socso:socsoE*4,eis:eisE}, leaveNotes:[],leaveThisPeriod:[],leaveBalance:null, grossEarnings:gross,totalDeductions:totDed,netPay:gross-totDed, status:'Draft' }); added++; } savePS();renderPSList(); toast(`โœ… ๅทฒๅŒฏๅ…ฅ ${added} ไปฝ Payslip${skipped?'๏ผŒ่ทณ้Ž '+skipped+' ไปฝ๏ผˆๅทฒๅญ˜ๅœจ๏ผ‰':''}`); }; inp.click(); } function quotNextId(){ const y=new Date().getFullYear(); const existing=QUOT_LIST.filter(q=>q.id&&q.id.startsWith('QT-'+y)); const maxN=existing.reduce((m,q)=>{const n=parseInt(q.id.split('-')[2]||0);return Math.max(m,n);},0); return'QT-'+y+'-'+String(maxN+1).padStart(3,'0'); } function supplierNextId(){const m=SUPPLIERS.reduce((x,s)=>Math.max(x,parseInt(s.id?.replace('SP','')||0)),0);return'SP'+String(m+1).padStart(4,'0');} function accCatOptions(sel){return ACC_CATS.map(c=>``).join('')+``;} function accNextId(){const max=ACC_TXNS.reduce((m,t)=>Math.max(m,parseInt(t.id?.replace('AT','')||0)),0);return'AT'+String(max+1).padStart(4,'0');} // Auto-fix: remove category names incorrectly saved as project names (function fixBadProjects(){ const CAT_PAT=/^(Office Expense|Office Expenses|Salary|Project Expenses?|Staff Claim|Medical Clam?)$/i; let changed=false; Object.values(TXN_OV).forEach(ov=>{ if(ov.projects&&Array.isArray(ov.projects)){ const fixed=ov.projects.filter(p=>p&&/^PJ\s*\d+/i.test(String(p).trim())); if(fixed.length!==ov.projects.length){ov.projects=fixed;changed=true;} } }); if(changed)localStorage.setItem('inzii_txn_ov',JSON.stringify(TXN_OV)); })(); let HR_EMPS=JSON.parse(localStorage.getItem('inzii_hr_emps')||'null')||JSON.parse(JSON.stringify(DEFAULT_HR_EMPS)); let HR_LEAVES=JSON.parse(localStorage.getItem('inzii_hr_leaves')||'null')||JSON.parse(JSON.stringify(DEFAULT_HR_LEAVES)); function saveCtEdits(){localStorage.setItem('inzii_ct_edits',JSON.stringify(CT_EDITS));} function saveTxnOv(){localStorage.setItem('inzii_txn_ov',JSON.stringify(TXN_OV));} function saveHREmps(){localStorage.setItem('inzii_hr_emps',JSON.stringify(HR_EMPS));} function saveHRLeaves(){localStorage.setItem('inzii_hr_leaves',JSON.stringify(HR_LEAVES));} // โ”€โ”€ Helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function getR(r){const ov=TXN_OV[r._uid||r.no];return ov?{...r,...ov}:r;} // โ”€โ”€ Bill Map: group by billInfo, compute balance from approved payments โ”€โ”€ let BILL_MAP=null; function buildBillMap(){ const map={}; DATA.forEach(r=>{ const mr=getR(r); const bill=(mr.billInfo||'').trim(); if(!bill||r.type==='Payment Received')return; if(!map[bill])map[bill]={quotAmt:0,approvedTotal:0,submittedTotal:0,latestDate:'',records:[]}; const d=mr.date||r.date||''; if(d>=map[bill].latestDate){map[bill].latestDate=d;if(mr.quotAmt)map[bill].quotAmt=mr.quotAmt;} if(mr.approvalDate)map[bill].approvedTotal+=(mr.submittedAmt||0); map[bill].submittedTotal+=(mr.submittedAmt||0); map[bill].records.push(r); }); Object.values(map).forEach(b=>{b.balance=Math.max(0,b.quotAmt-b.approvedTotal);}); return map; } function getBillMap(){if(!BILL_MAP)BILL_MAP=buildBillMap();return BILL_MAP;} function effBalance(r){ const mr=getR(r);const bill=(mr.billInfo||'').trim(); if(!bill)return mr.balanceInv!=null?mr.balanceInv:null; const bm=getBillMap(); return bm[bill]?bm[bill].balance:(mr.balanceInv!=null?mr.balanceInv:null); } function effQuotAmt(r){ const mr=getR(r);const bill=(mr.billInfo||'').trim(); if(!bill)return mr.quotAmt||0; const bm=getBillMap(); return bm[bill]?bm[bill].quotAmt:(mr.quotAmt||0); } function openBillDetail(bill){ if(!bill||bill==='โ€”')return; const bm=getBillMap(); const info=bm[bill]; const recs=DATA.filter(r=>(getR(r).billInfo||'').trim()===bill.trim()).sort((a,b)=>(a.date||'').localeCompare(b.date||'')); const approvedTotal=info?info.approvedTotal:0; const submittedTotal=info?info.submittedTotal:0; const quotAmt=info?info.quotAmt:0; const balance=info?info.balance:0; const pct=quotAmt>0?Math.min(100,(approvedTotal/quotAmt*100)).toFixed(1):0; const pendingAmt=Math.max(0,submittedTotal-approvedTotal); const firstR=recs[0]?getR(recs[0]):{}; const payee=firstR.payee||''; const projs=[...new Set(recs.flatMap(r=>(getR(r).projects||[])))]; const overallStatus=approvedTotal>=quotAmt&"Amt>0?'Fully Paid':approvedTotal>0?'Partially Paid':'Pending'; const statusColor=overallStatus==='Fully Paid'?'teal':overallStatus==='Partially Paid'?'green':'yellow'; showModal(`
๐Ÿ“„ ${bill}
${payee?`
${payee}
`:''} ${projs.length?`
${projs.map(p=>''+p+'').join('')}
`:''}
${overallStatus}
${quotAmt>0?`
Payment Progress ${pct}% Approved
${pendingAmt>0&"Amt>0?`
`:''}
โ–  Approved ${RM(approvedTotal)} ${pendingAmt>0?`โ–  Pending ${RM(pendingAmt)}`:''} โ–  Outstanding ${RM(balance)}
`:''}
${[['ๅ–ฎๆ“š็ธฝๆ•ธ',RM(quotAmt),'var(--accent)'],['ๅทฒ Submit',RM(submittedTotal),'var(--blue)'],['ๅทฒ Approved',RM(approvedTotal),'var(--green)'],['Outstanding',RM(balance),balance>0?'var(--yellow)':'var(--muted)']].map(([l,v,col])=>`
${l}
${v}
`).join('')}
Payment History
${recs.map((r,i)=>{ const mr=getR(r); const approved=!!mr.approvalDate; const amt=mr.submittedAmt||0; const label=mr.catLabel||mr.remarks||(i===0?'First Payment':'Payment #'+(i+1)); return`
${approved?'โœ…':'โณ'}
${label}
โˆ’${RM(amt)}
No. ${r.no} ๐Ÿ“… ${mr.date||'โ€”'} ${approved?`โœ“ Approved ${mr.approvalDate}`:`โš  Pending Approval`}
โ€บ
`; }).join('')}
${recs.length===0?`
No transactions linked to this bill
`:''}
`); } const CT_BASE={}; CT_PROFILES.forEach(c=>{if(c.companyName)CT_BASE[c.companyName.trim()]=c;}); function ctProfile(name){const b=CT_BASE[name.trim()]||{};const e=CT_EDITS[name.trim()]||{};const m={...b,...e};return Object.keys(m).length?m:null;} function pval(v,mono){if(!v||String(v).trim()==='')return'โ€”';return`${v}`;} function emptyState(msg){return`
๐Ÿ“ญ

${msg}

`;} function statusBadge(r){if(r.type==='Payment Received')return'';const mr=getR(r);if(mr.status==='Completed')return'Completed';if(mr.approvalDate)return'Approved';return'Pending';} function toast(msg,color){const el=document.createElement('div');el.className='toast';el.style.background=color||'var(--green)';el.textContent=msg;document.body.appendChild(el);requestAnimationFrame(()=>{el.style.opacity='1';setTimeout(()=>{el.style.opacity='0';setTimeout(()=>el.remove(),280)},2000);});} function kpi(cls,label,val,sub){return`
${label}
${val}
${sub?`
${sub}
`:''}
`;} // โ”€โ”€ Name normalization for leave matching โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const NAME_ALIAS={'YAP XING YI':'JANE YAP XING YI','LIM WEI NI':'LIM WEI NI'}; function normName(n){if(!n)return'';const u=n.trim().toUpperCase();return NAME_ALIAS[u]||u;} function empByName(name){const n=normName(name);return HR_EMPS.find(e=>e.name.toUpperCase()===n)||null;} // โ”€โ”€ Leave calculation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function calcLeave(emp,year){ const empUpper=emp.name.toUpperCase(); const empLeaves=HR_LEAVES.filter(l=>{ const ly=l.year||new Date(l.startDate).getFullYear(); return ly===year&&normName(l.empName)===empUpper; }); let alUsed=0,mcUsed=0,hlUsed=0,unpaidUsed=0,urgentUsed=0; empLeaves.forEach(l=>{ const t=(l.type||'').toLowerCase(); if(t.includes('annual'))alUsed+=l.days; else if(t.includes('hospital'))hlUsed+=l.days; else if(t.includes('medical')||t.includes('sick'))mcUsed+=l.days; else if(t.includes('unpaid'))unpaidUsed+=l.days; else if(t.includes('urgent'))urgentUsed+=l.days; }); const totalMC=mcUsed+hlUsed; if(emp.entType==='unlimited')return{entitled:null,alUsed,alBalance:null,mcUsed:totalMC,unpaidUsed,urgentUsed,empLeaves}; if(!emp.annualDays){return{entitled:0,alUsed,alBalance:0-alUsed,mcUsed:totalMC,unpaidUsed,urgentUsed,empLeaves};} const yearStart=new Date(year,0,1); const yearEnd=new Date(year,11,31); const today=new Date(); let start=new Date(yearStart); if(emp.confirmDate){const cd=new Date(emp.confirmDate);if(cd>yearStart&&cd.getFullYear()===year)start=cd;} let end=new Date(Math.min(yearEnd.getTime(),today.getTime())); if(emp.resignDate){const rd=new Date(emp.resignDate);if(rd=start){months=(end.getFullYear()-start.getFullYear())*12+(end.getMonth()-start.getMonth())+1;months=Math.min(months,12);} const proRated=Math.round((months/12)*emp.annualDays*2)/2; const carryOver=year===2026?(emp.carryOver2026||0):0; const entitled=carryOver+proRated; const alBalance=Math.round((entitled-alUsed)*10)/10; return{entitled,alUsed,alBalance,mcUsed:totalMC,unpaidUsed,urgentUsed,empLeaves}; } // โ”€โ”€ Export โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ let _curPage='dashboard'; function toggleExpMenu(){const m=document.getElementById('exp-menu');m.style.display=m.style.display==='none'?'block':'none';} document.addEventListener('click',e=>{if(!document.getElementById('exp-wrap')?.contains(e.target))document.getElementById('exp-menu').style.display='none';}); // โ”€โ”€ DATA BACKUP / RESTORE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function exportAllData(){ document.getElementById('exp-menu').style.display='none'; const data={}; const keys=['inzii_acc_txns','inzii_clients','inzii_suppliers','inzii_projects', 'inzii_inventory','inzii_quot_list','inzii_hr_emps','inzii_payslips', 'inzii_pv_list','inzii_cn_list','inzii_quot_settings','inzii_gmail_cfg', 'inzii_inventory_cats']; // also grab any keys we may have missed for(let i=0;i{const v=localStorage.getItem(k);if(v!==null){data[k]=v;count++;}}); const ts=new Date().toISOString().slice(0,16).replace('T','_').replace(':',''); const blob=new Blob([JSON.stringify(data,null,2)],{type:'application/json'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=`inzii-data-backup-${ts}.json`; a.click(); toast(`โœ… ๅทฒๅŒฏๅ‡บ ${count} ้ …่ณ‡ๆ–™`,'var(--green)'); } function importAllDataModal(){ document.getElementById('exp-menu').style.display='none'; document.getElementById('data_import_modal')?.remove(); const div=document.createElement('div'); div.id='data_import_modal'; div.style.cssText='position:fixed;inset:0;background:rgba(35,31,32,.55);z-index:300;display:flex;align-items:center;justify-content:center'; div.onclick=e=>{if(e.target===div)div.remove();}; div.innerHTML=`
๐Ÿ“‚
Restore All Data
โš ๏ธ ้€™ๆœƒ่ฆ†่“‹็›ฎๅ‰ๆ‰€ๆœ‰่ณ‡ๆ–™ใ€‚่ซ‹็ขบ่ชๅทฒ้ธๆ“‡ๆญฃ็ขบ็š„ๅ‚™ไปฝๆช”ๆกˆใ€‚
๐Ÿ“„
้ปžๆ“Š้ธๆ“‡ๆˆ–ๆ‹–ๆ›ณ JSON ๅ‚™ไปฝๆช”ๆกˆ
inzii-data-backup-*.json
`; document.body.appendChild(div); } let _pendingImportData=null; function _handleDataFile(file){ if(!file){return;} const status=document.getElementById('di_status'); const btn=document.getElementById('di_confirm_btn'); if(!file.name.endsWith('.json')){status.innerHTML='โŒ ่ซ‹้ธๆ“‡ .json ๆช”ๆกˆ';return;} const reader=new FileReader(); reader.onload=e=>{ try{ const data=JSON.parse(e.target.result); const count=Object.keys(data).length; _pendingImportData=data; if(btn)btn.disabled=false; if(status)status.innerHTML=`โœ… ๅทฒ่ฎ€ๅ– ${count} ้ …่ณ‡ๆ–™๏ผŒ้ปžๆ“Šใ€ŒๅŒฏๅ…ฅไธฆ้‡ๆ–ฐ่ผ‰ๅ…ฅใ€ๅฎŒๆˆๆฌ็งป`; document.getElementById('di_drop').style.borderColor='var(--green)'; }catch{ _pendingImportData=null; if(btn)btn.disabled=true; if(status)status.innerHTML='โŒ ๆช”ๆกˆๆ ผๅผ้Œฏ่ชค๏ผŒ่ซ‹้ธๆ“‡ๆญฃ็ขบ็š„ๅ‚™ไปฝๆช”ๆกˆ'; } }; reader.readAsText(file); } function _confirmDataImport(){ if(!_pendingImportData){return;} if(!confirm('็ขบๅฎš่ฆ่ฆ†่“‹็›ฎๅ‰ๆ‰€ๆœ‰่ณ‡ๆ–™ๅ—Ž๏ผŸ\n\nๆญคๆ“ไฝœ็„กๆณ•้‚„ๅŽŸใ€‚'))return; Object.entries(_pendingImportData).forEach(([k,v])=>localStorage.setItem(k,v)); toast('โœ… ่ณ‡ๆ–™ๅทฒๅŒฏๅ…ฅ๏ผŒ้‡ๆ–ฐ่ผ‰ๅ…ฅไธญ...','var(--green)'); setTimeout(()=>location.reload(),800); } function doExportPDF(){ document.getElementById('exp-menu').style.display='none'; // Show orientation picker document.getElementById('mt').textContent='๐Ÿ“„ Export PDF'; document.getElementById('mb').innerHTML=`

้ธๆ“‡็‰ˆ้ขๆ–นๅ‘ / Choose page orientation

`; document.getElementById('mo').classList.add('show'); } function triggerPrint(orient){ closeModal(); // Inject dynamic @page rule let styleEl=document.getElementById('_print_orient'); if(!styleEl){styleEl=document.createElement('style');styleEl.id='_print_orient';document.head.appendChild(styleEl);} styleEl.textContent=`@media print{@page{size:A4 ${orient};margin:1.5cm;}}`; const title=document.getElementById('tt').textContent; const orig=document.title; document.title='Inzii โ€” '+title; setTimeout(()=>{window.print();document.title=orig;},100); } function quotExportExcel(){ const fmtA=n=>(+n||0).toFixed(2); const rows=[['Quotation No','Revision','Date','Client','Project / Remarks','Handler','Type','Amount (MYR)','Status']]; const groups={}; (QUOT_LIST||[]).forEach(x=>{if(!groups[x.quotNo])groups[x.quotNo]=[];groups[x.quotNo].push(x);}); Object.values(groups).forEach(revs=>{ revs.sort((a,b)=>(b.revision||0)-(a.revision||0)); revs.forEach(q=>{ rows.push([q.id||q.quotNo||'',q.revision||0,q.date||q.wonDeal||'',q.client||'',q.remarks||q.tag||'',q.handler||'',q.quotType||'',fmtA(+q.finalAmt||+q.totalAmt||0),q.status||'']); }); }); _csvDownload(rows,'Quotations'); } function exportSingleQuot(id){ const q=QUOT_LIST.find(x=>x.id===id); if(!q){toast('Quotation not found','var(--red)');return;} const fmtA=n=>(+n||0).toFixed(2); const rows=[]; // Header info rows.push(['Quotation No.',q.id||'']); rows.push(['Date',q.date||'']); rows.push(['Client',q.client||'']); rows.push(['Contact',q.clientPhone||'']); rows.push(['Address',q.clientAddress||'']); rows.push(['Project / Remarks',q.remarks||'']); rows.push(['Handler',q.handler||'']); rows.push(['Type',q.quotType||'']); rows.push(['Status',q.status||'']); rows.push([]); // Section items rows.push(['Section','Item No.','Description','Details / Dimension','Qty','Unit','Unit Rate (MYR)','Amount (MYR)','FOC']); let itemNo=1; (q.sections||[]).forEach(sec=>{ const secLabel=sec.optional?`[Optional] ${sec.title||''}`:sec.title||''; (sec.items||[]).forEach(it=>{ if(it.type==='subhdr'){ rows.push([secLabel,'',it.title||'','','','','','','']); } else { const amt=it.foc?0:(+(it.qty)||0)*(+(it.rate)||0); rows.push([secLabel,itemNo++,it.desc||'',it.desc2||'',+(it.qty)||0,it.unit||'pcs',fmtA(+(it.rate)||0),fmtA(amt),it.foc?'YES':'']); } }); }); rows.push([]); // Totals rows.push(['','','','','','','Subtotal',fmtA(q.totalAmt||0),'']); if(q.discountAmt>0)rows.push(['','','','','','','Discount','-'+fmtA(q.discountAmt),'']); rows.push(['','','','','','','TOTAL (MYR)',fmtA(q.finalAmt||q.totalAmt||0),'']); // Payment terms const pt=QUOT_PT[q.paymentTerm]||[]; if(pt.length){ rows.push([]); rows.push(['Payment Terms']); pt.forEach((t,i)=>rows.push([`Stage ${i+1}`,t.label||'',t.pct?t.pct+'%':'',fmtA((q.finalAmt||0)*(+(t.pct)||0)/100)])); } _csvDownload(rows,id.replace(/\s/g,'_')); } function inventoryExportExcel(){ const rows=[['Item Name','Category','Unit','Cost (MYR)','Selling Price (MYR)','Margin (%)','Remarks']]; const items=JSON.parse(localStorage.getItem('inzii_inventory')||'[]'); items.forEach(item=>{ const cost=+item.cost||0;const sell=+item.sellPrice||0; const margin=cost>0?((sell-cost)/cost*100).toFixed(1):'โ€”'; rows.push([item.name||'',item.category||'',item.unit||'',cost.toFixed(2),sell.toFixed(2),margin,item.remarks||'']); }); _csvDownload(rows,'Inventory'); } function _csvDownload(rows,name){ if(!rows||rows.length<2){toast('No data to export','var(--red)');return;} const esc=v=>'"'+String(v==null?'':v).replace(/"/g,'""')+'"'; const csv='\uFEFF'+rows.map(r=>r.map(esc).join(',')).join('\r\n'); const fname=name+'_'+new Date().toISOString().slice(0,10)+'.csv'; const a=document.createElement('a'); a.href='data:text/csv;charset=utf-8,'+encodeURIComponent(csv); a.setAttribute('download',fname); a.style.display='none'; document.body.appendChild(a); a.click(); setTimeout(()=>document.body.removeChild(a),100); toast('\u2705 Exported '+(rows.length-1)+' rows','var(--green)'); } function qtExportExcel(){ const fmtA=n=>(+n||0).toFixed(2); const rows=[['Quotation No','Date','Client','Type','Contract (MYR)','Paid (MYR)','Outstanding (MYR)','Payment Term','Status','Remarks']]; QUOT_LIST.filter(q=>q.status==='Won').forEach(q=>{ const paid=(q.payments||[]).reduce((s,p)=>s+(+p.amount||0),0); const contract=+q.finalAmt||0; rows.push([q.id||'',q.wonDeal||q.date||'',q.client||'',q.quotType||'',fmtA(contract),fmtA(paid),fmtA(contract-paid),q.paymentTerm||'',q.status||'',q.remarks||'']); }); _csvDownload(rows,'Sales_Projects'); } function piExportExcel(){ const fmtA=n=>(+n||0).toFixed(2); const rows=[['PI No','Date','Client','Quotation','Amount (MYR)','Status','Notes']]; QUOT_LIST.forEach(q=>(q.pis||[]).forEach(p=>{ rows.push([p.piNo||'',p.date||'',q.client||'',q.id||'',fmtA(p.amount),p.status||'',p.notes||'']); })); _csvDownload(rows,'Proforma_Invoices'); } function invExportExcel(){ const fmtA=n=>(+n||0).toFixed(2); const rows=[['Invoice No','Date','Client','Quotation','Amount (MYR)','Status','Notes']]; QUOT_LIST.forEach(q=>(q.invoices||[]).forEach(i=>{ rows.push([i.invNo||'',i.date||'',q.client||'',q.id||'',fmtA(i.amount),i.status||'',i.notes||'']); })); _csvDownload(rows,'Invoices'); } async function exportViewHTML(){ document.getElementById('exp-menu').style.display='none'; const fmtA=n=>(+n||0).toLocaleString('en-MY',{minimumFractionDigits:2,maximumFractionDigits:2}); const fmtD=d=>{if(!d)return'โ€”';const p=d.split('-');return p.length===3?`${p[2]}-${p[1]}-${p[0]}`:d;}; const co=QUOT_SETTINGS.companyName||QUOT_CO.name||'INZII'; const now=new Date().toLocaleDateString('en-MY',{day:'2-digit',month:'short',year:'numeric'})+' '+new Date().toLocaleTimeString('en-MY',{hour:'2-digit',minute:'2-digit'}); // โ”€โ”€ Pre-render PDF HTML for all won deals using monkey-patch capture โ”€โ”€ const pdfCache={}; const _sj=o=>JSON.stringify(o).replace(/<\/script>/gi,'<\\/script>').replace(/`; const blob=new Blob([html],{type:'text/html;charset=utf-8'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download='inzii-view-'+new Date().toISOString().slice(0,10)+'.html'; document.body.appendChild(a);a.click(); setTimeout(()=>{document.body.removeChild(a);URL.revokeObjectURL(a.href);},1000); const pdfCount=Object.keys(pdfCache).filter(k=>pdfCache[k]).length; toast(`View exported โœ“ (${wonDeals.length} projects, ${pdfCount} PDFs embedded)`,'var(--green)'); } function doExportExcel(){ document.getElementById('exp-menu').style.display='none'; const page=_curPage; const title=document.getElementById('tt').textContent; let rows=[]; // Account System pages if(page==='account_txns'){exportAccToExcel();return;} if(page==='projects'){exportProjectOverview();return;} if(page==='clients'){ rows=[['ID','Name','Contact No','Address','Project Code','Remarks']]; CLIENTS.forEach(cl=>rows.push([cl.id,cl.name||'',cl.contactNo||'',cl.address||'',cl.projectCode||'',cl.remarks||''])); _csvDownload(rows,'Inzii_Clients');return; } if(page==='suppliers'){ rows=[['ID','Company Name','Bank','Bank Account','Phone','Email','Address','Business Activities','TIN No','SSM No']]; SUPPLIERS.forEach(s=>rows.push([s.id,s.companyName||'',s.bankName||'',s.bankAccount||'',s.companyPhone||'',s.companyEmail||'',s.companyAddress||'',s.businessActivities||'',s.tinNo||'',s.ssmNo||''])); _csvDownload(rows,'Inzii_Suppliers');return; } if(page==='transactions'){ const q=(document.getElementById('ts')?.value||'').toLowerCase(); const type=document.getElementById('tt2')?.value||''; const month=document.getElementById('tm')?.value||''; const cat=document.getElementById('tc')?.value||''; const f=DATA.filter(r=>{const mr=getR(r); if(type&&r.type!==type)return false; if(month&&!mr.date.startsWith(month))return false; if(cat&&mr.cat!==cat)return false; if(q){const h=[mr.payee,mr.billInfo,(mr.projects||[]).join(','),mr.cat,mr.catLabel,mr.remarks].join(' ').toLowerCase();if(!h.includes(q))return false;} return true; }); rows=[['No','Date','Type','Payee','Project','Category','Bill Info','Inv/Quot Amt','Paid Amt','Outstanding','Approval Date','Remarks']]; f.forEach(r=>{const mr=getR(r);rows.push([mr.no,mr.date,r.type,mr.payee,(mr.projects||[]).join(', '),mr.catLabel||mr.cat,mr.billInfo,mr.quotAmt||'',r.type==='Payment Received'?mr.amtReceived:mr.submittedAmt,mr.balanceInv||0,mr.approvalDate||'',mr.remarks||'']);}); } else if(page==='projectdetail'){ toast('่ซ‹ๅพž Project Overview ้ ้ขไฝฟ็”จ Export CSV','var(--yellow)');return; } else if(page==='projects'){ const pm={}; DATA.forEach(r=>{const mr=getR(r);const pjs=mr.projects||r.projects||[];pjs.forEach(p=>{if(!pm[p])pm[p]={inc:0,exp:0};if(r.type==='Payment Received')pm[p].inc+=mr.amtReceived||0;else pm[p].exp+=(mr.submittedAmt||0)/Math.max(pjs.length,1);});}); rows=[['Project','Income (RM)','Expenses (RM)','Net P&L (RM)']]; Object.entries(pm).sort((a,b)=>a[0].localeCompare(b[0])).forEach(([pj,d])=>rows.push([pj,d.inc,d.exp,d.inc-d.exp])); rows.push(['TOTAL',Object.values(pm).reduce((s,d)=>s+d.inc,0),Object.values(pm).reduce((s,d)=>s+d.exp,0),Object.values(pm).reduce((s,d)=>s+d.inc-d.exp,0)]); } else if(page==='expenses'){ const cm={};CREATES.forEach(r=>{const mr=getR(r);const c=mr.catLabel||mr.cat||'Other';if(!cm[c])cm[c]={t:0,n:0,group:mr.cat};cm[c].t+=(mr.submittedAmt||0);cm[c].n++;}); rows=[['Category','Group','Transactions','Total (RM)']]; Object.entries(cm).sort((a,b)=>b[1].t-a[1].t).forEach(([c,d])=>rows.push([c,d.group,d.n,d.t])); } else if(page==='unapproved'){ const f=CREATES.filter(r=>!getR(r).approvalDate); rows=[['No','Date','Payee','Project','Category','Bill Info','Inv/Quot Amt','Submitted Amt','Outstanding','Remarks']]; f.forEach(r=>{const mr=getR(r);rows.push([mr.no,mr.date,mr.payee,(mr.projects||[]).join(', '),mr.catLabel||mr.cat,mr.billInfo,mr.quotAmt||'',mr.submittedAmt,mr.balanceInv||0,mr.remarks||'']);}); } else if(page==='contractors'){ const list=buildCtFromTxn(); rows=[['Payee Name','Company Name','TIN No.','SSM No.','Phone','Projects','Total Txns','Total Paid (RM)']]; list.forEach(c=>{const p=ctProfile(c.name)||{};rows.push([c.name,p.companyName||'',p.tinNumber||'',p.ssmNumber||'',p.phone||'',[...c.projs].join(', '),c.txns.length,c.total]);}); } else if(page==='payroll'){ const sal=DATA.filter(r=>r.docCat==='Salary Expenses'&&r.type==='Payment Create'); rows=[['Date','Payee','Bank','Account No','Amount (RM)','Approval Date']]; sal.forEach(r=>rows.push([r.date,r.payee,r.bank,r.accNo,r.submittedAmt,r.approvalDate||''])); } else if(page==='staffprofiles'){ rows=[['Emp No','Name','IC','DOB','Phone','Email','Department','Bank','Account No','EPF No','Tax No','Status']]; HR_EMPS.forEach(e=>rows.push([e.empNo,e.name,e.ic,e.dob,e.phone,e.email,e.position,e.bank,e.bankAccount,e.epfNo,e.taxNo,e.resigned?'Resigned':'Active'])); } else if(page==='leavemgmt'){ rows=[['ID','Employee','Type','Start Date','End Date','Days','Year','Remarks']]; HR_LEAVES.forEach(l=>rows.push([l.id,l.empName,l.type,l.startDate,l.endDate,l.days,l.year,l.remarks||''])); }else if(page==='settings'){c.innerHTML=settingsPage();} else if(page==='accountsummary'){ // Build monthly P&L table rows=[['Section','Item',...ACCT_MONTHS.map(m=>MLF[m]),'Total']]; if(_acctData){ ACCT_STRUCTURE.forEach(sec=>{ sec.items.forEach(item=>{ const monthVals=ACCT_MONTHS.map(mo=>_acctData[mo]?.[sec.key+'_'+item.label]||0); rows.push([sec.section,item.label,...monthVals,monthVals.reduce((s,v)=>s+v,0)]); }); }); } } else if(page==='dashboard'){ rows=[['Month','Income (RM)','Expenses (RM)','Net P&L (RM)']]; const mOut={},mIn={};MONTHS.forEach(m=>{mOut[m]=0;mIn[m]=0;}); DATA.forEach(r=>{const mr=getR(r);const m=mr.date?mr.date.slice(0,7):'';if(!MONTHS.includes(m))return;if(r.type==='Payment Create')mOut[m]+=(mr.submittedAmt||0);else mIn[m]+=(mr.amtReceived||0);}); MONTHS.forEach(m=>rows.push([MLF[m]+' 2026',mIn[m],mOut[m],mIn[m]-mOut[m]])); rows.push(['TOTAL',MONTHS.reduce((s,m)=>s+mIn[m],0),MONTHS.reduce((s,m)=>s+mOut[m],0),MONTHS.reduce((s,m)=>s+mIn[m]-mOut[m],0)]); } else if(page==='payslip'){ const mo=document.getElementById('psm')?.value||''; const q=(document.getElementById('psq')?.value||'').toLowerCase(); const filtered=PS_LIST.filter(p=>{ if(mo&&p.periodLabel!==mo)return false; if(q&&!(p.empName||'').toLowerCase().includes(q)&&!(p.empNo||'').toLowerCase().includes(q))return false; return true; }); rows=[['PAY PERIOD','EMPLOYEE','BANK NAME','BANK ACCOUNT','NET PAY (RM)']]; filtered.forEach(p=>{ const emp=HR_EMPS.find(e=>e.empNo===p.empNo)||{}; rows.push([p.periodLabel,p.empName,emp.bank||'',emp.bankAccount||'',(+p.netPay||0).toFixed(2)]); }); _csvDownload(rows,'Inzii_Payslips'+(mo?'_'+mo.replace(/\s/g,'_'):''));return; } else if(page==='quotations'){quotExportExcel();return; } else if(page==='qt_projects'){qtExportExcel();return; } else if(page==='pi_records'){piExportExcel();return; } else if(page==='invoices'){invExportExcel();return; } else if(page==='receipts'){pmExportCSV();return; } else if(page==='inventory'){inventoryExportExcel();return; } else if(page==='pv_records'){pvExportExcel();return; } else if(page==='cn_records'){cnExportExcel();return; } else if(page==='er_records'){erExportExcel();return; } else if(page==='payrollsummary'){ const _period=document.getElementById('psum_period')?.value; const _statusF=document.getElementById('psum_status')?.value; const _empF=document.getElementById('psum_emp')?.value||''; const _isAll=_period==='__ALL__'; const _list=_isAll?PS_LIST:PS_LIST.filter(p=>p.periodLabel===_period); // Build aggregated rowData same as renderPayrollSummary let _rowData; if(_isAll){ const _em={}; _list.forEach(p=>{ if(_empF&&p.empNo!==_empF)return; if(!_em[p.empNo]){ const emp=HR_EMPS.find(e=>e.empNo===p.empNo); if(_statusF==='active'&&emp?.resigned)return; _em[p.empNo]={empNo:p.empNo,empName:p.empName,department:p.department||'', basic:0,comm:0,allow:0,incentive:0,grossEarnings:0,unpaid:0, epf:0,socso:0,eis:0,tax:0,totalDeductions:0,netPay:0, emp_epf:0,emp_socso:0,emp_eis:0,resigned:emp?.resigned}; } const a=_em[p.empNo]; a.basic+=((p.earnings||[]).find(e=>e.desc==='BASIC PAY')?.amount||0); a.comm+=(p.earnings||[]).filter(e=>e.desc==='COMMISSION').reduce((s,e)=>s+(+e.amount||0),0); a.allow+=(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('allowance')||((e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&(e.remark||'').toUpperCase().includes('ALLOWANCE')))).reduce((s,e)=>s+(+e.amount||0),0); a.incentive+=(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&!e.desc.toLowerCase().includes('allowance')&&!(e.remark||'').toUpperCase().includes('ALLOWANCE')).reduce((s,e)=>s+(+e.amount||0),0); a.grossEarnings+=(p.grossEarnings||0); a.unpaid+=(p.ded?.unpaid||0); a.epf+=(p.ded?.epf||0);a.socso+=(p.ded?.socso||0);a.eis+=(p.ded?.eis||0);a.tax+=(p.ded?.tax||0); a.totalDeductions+=(p.totalDeductions||0);a.netPay+=(p.netPay||0); a.emp_epf+=(p.emp?.epf||0);a.emp_socso+=(p.emp?.socso||0);a.emp_eis+=(p.emp?.eis||0); }); _rowData=Object.values(_em).sort((a,b)=>a.empNo.localeCompare(b.empNo)).map(a=>({ empNo:a.empNo,empName:a.empName,dept:a.department, basic:a.basic,comm:a.comm,allow:a.allow,incentive:a.incentive, gross:a.grossEarnings,unpaid:a.unpaid, epf:a.epf,socso:a.socso,eis:a.eis,tax:a.tax, totDed:a.totalDeductions,net:a.netPay, eEpf:a.emp_epf,eSoc:a.emp_socso,eEis:a.emp_eis, status:a.resigned?'Resigned':'Active' })); } else { _rowData=_list.filter(p=>{ if(_empF&&p.empNo!==_empF)return false; if(_statusF==='active'){const emp=HR_EMPS.find(e=>e.empNo===p.empNo);return!emp?.resigned;} return true; }).sort((a,b)=>a.empNo.localeCompare(b.empNo)).map(p=>{ const emp=HR_EMPS.find(e=>e.empNo===p.empNo)||{}; return{ empNo:p.empNo,empName:p.empName,dept:p.department||'', basic:((p.earnings||[]).find(e=>e.desc==='BASIC PAY')?.amount||0), comm:(p.earnings||[]).filter(e=>e.desc==='COMMISSION').reduce((s,e)=>s+(+e.amount||0),0), allow:(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('allowance')||((e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&(e.remark||'').toUpperCase().includes('ALLOWANCE')))).reduce((s,e)=>s+(+e.amount||0),0), incentive:(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&!e.desc.toLowerCase().includes('allowance')&&!(e.remark||'').toUpperCase().includes('ALLOWANCE')).reduce((s,e)=>s+(+e.amount||0),0), gross:(p.grossEarnings||0),unpaid:(p.ded?.unpaid||0), epf:(p.ded?.epf||0),socso:(p.ded?.socso||0),eis:(p.ded?.eis||0),tax:(p.ded?.tax||0), totDed:(p.totalDeductions||0),net:(p.netPay||0), eEpf:(p.emp?.epf||0),eSoc:(p.emp?.socso||0),eEis:(p.emp?.eis||0), status:emp.resigned?'Resigned':'Active' }; }); } const _n=v=>(+v||0).toFixed(2); const _hdr=['#','Emp No','Name','Department','Basic (RM)','Commission (RM)','Allowance (RM)','Incentive (RM)','Gross Earning (RM)','Unpaid Leave (RM)','EPF - Emp (RM)','SOCSO - Emp (RM)','EIS - Emp (RM)','Tax / PCB (RM)','Total Deductions (RM)','Net Pay (RM)','EPF - Employer (RM)','SOCSO - Employer (RM)','EIS - Employer (RM)','Status']; rows=[_hdr]; _rowData.forEach((r,i)=>rows.push([i+1,r.empNo,r.empName,r.dept,_n(r.basic),_n(r.comm),_n(r.allow),_n(r.incentive),_n(r.gross),_n(r.unpaid),_n(r.epf),_n(r.socso),_n(r.eis),_n(r.tax),_n(r.totDed),_n(r.net),_n(r.eEpf),_n(r.eSoc),_n(r.eEis),r.status])); // TOTAL row const _sum=k=>_rowData.reduce((s,r)=>s+(+r[k]||0),0); rows.push(['','TOTAL ('+_rowData.length+' staff)','','',_n(_sum('basic')),_n(_sum('comm')),_n(_sum('allow')),_n(_sum('incentive')),_n(_sum('gross')),_n(_sum('unpaid')),_n(_sum('epf')),_n(_sum('socso')),_n(_sum('eis')),_n(_sum('tax')),_n(_sum('totDed')),_n(_sum('net')),_n(_sum('eEpf')),_n(_sum('eSoc')),_n(_sum('eEis')),'']); const _label=_isAll?'Full_Year_2026':(_period||'').replace(/\s/g,'_'); _csvDownload(rows,'Inzii_Payroll_Summary_'+_label);return; } else { toast('No export available for this page','var(--yellow)');return; } if(!rows.length){toast('No export available for this page','var(--yellow)');return;} _csvDownload(rows,'Inzii_'+title.replace(/[^a-zA-Z0-9]/g,'_')); } // โ”€โ”€ Navigation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function nav(page,el){ const RO_PAGES=['qt_projects','pi_records','receipts','invoices','account_txns']; if(READONLY&&!RO_PAGES.includes(page)){page='qt_projects';el=document.querySelector('.nav-item[onclick*="qt_projects"]');} _curPage=page; document.querySelectorAll('.nav-item,.nav-sub-item').forEach(n=>n.classList.remove('active')); if(el)el.classList.add('active'); const T={payslip:'Payslip Generator',payroll:'Staff & Payroll',payrollsummary:'Payroll Monthly Summary',staffprofiles:'Staff Profiles',leavemgmt:'Leave Management',settings:'Settings',acc_summary:'Account Summary',projects:'Project Overview',account_txns:'Transactions',clients:'Client Details',suppliers:'Supplier Details',inventory:'Inventory',pv_records:'Payment Voucher',cn_records:'Credit Note',quotations:'Quotations',qt_projects:'Sales Projects',pi_records:'Proforma Invoice Records',invoices:'Invoices',receipts:'Receipts',quot_settings:'QT Settings'}; const B={payslip:'HR โ€บ Payslip',payroll:'HR โ€บ Payroll',payrollsummary:'HR โ€บ Payroll Summary',staffprofiles:'HR โ€บ Staff Profiles',leavemgmt:'HR โ€บ Leave Management',acc_summary:'Account โ€บ Summary',projects:'Account โ€บ Projects',account_txns:'Account โ€บ Transactions',clients:'Account โ€บ Clients',suppliers:'Account โ€บ Suppliers',inventory:'Quotation System โ€บ Inventory',pv_records:'Account โ€บ Payment Voucher',cn_records:'Account โ€บ Credit Note',quotations:'Quotation System โ€บ Quotations',qt_projects:'Quotation System โ€บ Sales Projects',pi_records:'Quotation System โ€บ Proforma Invoice',invoices:'Quotation System โ€บ Invoices',receipts:'Quotation System โ€บ Receipts',quot_settings:'Quotation System โ€บ Settings'}; document.getElementById('tt').textContent=T[page]||page; document.getElementById('tb').textContent=B[page]||page; const c=document.getElementById('content'); if(page==='payroll')c.innerHTML=hrPayrollPage(); else if(page==='payrollsummary'){c.innerHTML=payrollSummaryPage();initPayrollSummary();} else if(page==='staffprofiles'){c.innerHTML=staffProfilesPage();filterStaff('');} else if(page==='leavemgmt'){c.innerHTML=leaveMgmtPage();renderLeaveTable();} else if(page==='payslip'){c.innerHTML=payslipPage();renderPSList();} else if(page==='acc_summary'){c.innerHTML=accountSummaryPage();} else if(page==='projects'){c.innerHTML=projectOverviewPage();renderProjectOverview();} else if(page==='account_txns'){c.innerHTML=accountSystemPage();renderAccTxns();} else if(page==='clients'){c.innerHTML=clientsPage();renderClients();} else if(page==='suppliers'){c.innerHTML=suppliersPage();renderSuppliers();} else if(page==='inventory'){c.innerHTML=inventoryPage();renderInventory();} else if(page==='pv_records'){c.innerHTML=pvPage();renderPVs();} else if(page==='cn_records'){c.innerHTML=cnPage();renderCNs();} else if(page==='er_records'){c.innerHTML=erPage();renderERs();} else if(page==='quotations'){c.innerHTML=quotationsPage();renderQuotations();} else if(page==='qt_projects'){c.innerHTML=qtProjectsPage();renderQtProjects();} else if(page==='pi_records'){renderPIRecordsPage();} else if(page==='invoices'){renderInvoicesPage();} else if(page==='receipts'){renderPaymentsPage();} else if(page==='quot_settings'){c.innerHTML=quotSettingsPage();renderQuotSettings();} else if(page==='settings'){c.innerHTML=settingsPage();} if(READONLY)setTimeout(applyReadonly,50); } function applyReadonly(){ if(!READONLY)return; const c=document.getElementById('content');if(!c)return; // Hide action buttons (save, delete, approve, new, add, edit) c.querySelectorAll('.btn-save,.btn-danger,.btn-approve').forEach(b=>b.style.display='none'); c.querySelectorAll('button.btn,.rt-btn').forEach(b=>{ const txt=(b.textContent||'').trim().toLowerCase(); const oc=(b.getAttribute('onclick')||'').toLowerCase(); const hide=['new ','+ ','add ','delete','edit','save','record payment','void','approve','generate','send','upload','import','export receipt','record inv','new inv','new pi','new payment']; if(hide.some(h=>txt.startsWith(h)||txt===h.trim())|| oc.includes('openmodal')||oc.includes('newpi')||oc.includes('newinv')|| oc.includes('newreceipt')||oc.includes('openinvmodal')||oc.includes('deleteinv')|| oc.includes('voidpi')||oc.includes('editpi')||oc.includes('saveinv')|| oc.includes('recordpayment')||oc.includes('approvepi')){ b.style.display='none'; } }); // Make all non-filter inputs read-only c.querySelectorAll('input:not(.filter-input),textarea,select:not(.filter-select)').forEach(el=>{ el.setAttribute('disabled','disabled'); el.style.pointerEvents='none';el.style.opacity='.7'; }); } function navToTxns(cat,type){ const navEl=document.querySelector('.nav-sub-item[onclick*="account_txns"]'); nav('account_txns',navEl); setTimeout(()=>{ const typeEl=document.getElementById('acc_type'); const catEl=document.getElementById('acc_cat'); if(typeEl&&type)typeEl.value=type; if(catEl&&cat)catEl.value=cat; renderAccTxns(); },50); } function navToAccOffice(q){ // Navigate to Transactions filtered by Office Expense + search keyword const navEl=document.querySelector('.nav-sub-item[onclick*="account_txns"]'); nav('account_txns',navEl); setTimeout(()=>{ const catEl=document.getElementById('acc_cat'); const qEl=document.getElementById('acc_q'); const typeEl=document.getElementById('acc_type'); if(catEl)catEl.value='Office Expense'; if(typeEl)typeEl.value='out'; if(qEl)qEl.value=q; renderAccTxns(); },50); } function navToAccProj(code){ // Navigate to Transactions filtered by Project Expense + project code const navEl=document.querySelector('.nav-sub-item[onclick*="account_txns"]'); nav('account_txns',navEl); setTimeout(()=>{ const catEl=document.getElementById('acc_cat'); const projEl=document.getElementById('acc_proj'); const typeEl=document.getElementById('acc_type'); if(catEl)catEl.value='Project Expense'; if(typeEl)typeEl.value='out'; if(projEl)projEl.value=code; _accIdFilter=null; renderAccTxns(); },50); } function navToAccIncomeProj(code){ const navEl=document.querySelector('.nav-sub-item[onclick*="account_txns"]'); nav('account_txns',navEl); setTimeout(()=>{ const typeEl=document.getElementById('acc_type'); const projEl=document.getElementById('acc_proj'); if(typeEl)typeEl.value='in'; if(projEl&&code!=='(No Project)')projEl.value=code; _accIdFilter=null; renderAccTxns(); },50); } function navToAccUnmatched(){ // Navigate to Transactions showing only the unmatched Office Expense IDs const navEl=document.querySelector('.nav-sub-item[onclick*="account_txns"]'); nav('account_txns',navEl); setTimeout(()=>{ const catEl=document.getElementById('acc_cat'); const typeEl=document.getElementById('acc_type'); const qEl=document.getElementById('acc_q'); if(catEl)catEl.value='Office Expense'; if(typeEl)typeEl.value='out'; if(qEl)qEl.value=''; _accIdFilter=[..._summaryUnmatchedIds]; renderAccTxns(); },50); } // โ”€โ”€ PAYROLL (from transaction data) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function hrPayrollPage(){ const sal=DATA.filter(r=>getR(r).cat==='Salary Expenses'&&r.type==='Payment Create'); if(!sal.length)return emptyState('ๅฐšๆœช่ผ‰ๅ…ฅ่–ช่ณ‡่ณ‡ๆ–™'); // Build nameโ†’empNo lookup from HR_EMPS const empNoMap={};HR_EMPS.forEach(e=>{if(e.name&&e.empNo)empNoMap[e.name.trim().toUpperCase()]=e.empNo;}); const st={};sal.forEach(r=>{ const mr=getR(r);const key=mr.payee||r.payee; if(!st[key]){const en=empNoMap[(mr.payee||r.payee)?.trim().toUpperCase()]||'';st[key]={name:mr.payee||r.payee,months:{},total:0,emp:en};} const m=mr.date?mr.date.slice(0,7):''; st[key].months[m]=(st[key].months[m]||0)+(mr.submittedAmt||0); st[key].total+=(mr.submittedAmt||0); }); const sl=Object.values(st).sort((a,b)=>{const na=parseInt((a.emp||'').replace(/\D/g,''))||9999;const nb=parseInt((b.emp||'').replace(/\D/g,''))||9999;return na-nb;});const tS=sl.reduce((s,e)=>s+e.total,0); return`
${kpi('blue','Staff on Payroll',''+sl.length)}${kpi('red','Total Salary (YTD)',RM(tS))}${kpi('yellow','Avg Monthly',RM(tS/6))}

๐Ÿ’ฐ Salary by Staff

${MONTHS.map(m=>``).join('')} ${sl.map(e=>`${MONTHS.map(m=>``).join('')}`).join('')} ${MONTHS.map(m=>{const t=sal.filter(r=>getR(r).date&&getR(r).date.startsWith(m)).reduce((s,r)=>s+(getR(r).submittedAmt||0),0);return``;}).join('')}
EmployeeEmp No${ML[m]}Total
${e.name}${e.emp||'โ€”'}${e.months[m]?fmt(e.months[m]):'โ€”'}${fmt(e.total)}
TOTAL${fmt(t)}${fmt(tS)}
`; } function openPayrollDetail(name,emp){ const txns=DATA.filter(r=>r.payee===name&&getR(r).cat==='Salary Expenses'&&r.type==='Payment Create').sort((a,b)=>a.date.localeCompare(b.date)); const total=txns.reduce((s,r)=>s+(r.submittedAmt||0),0); document.getElementById('mt').textContent=`๐Ÿ’ฐ ${name} โ€” Payroll Detail`; document.getElementById('mb').innerHTML=`
Emp No: ${emp||'โ€”'}
Records: ${txns.length}
YTD Total: RM ${fmt(total)}
${txns.map(r=>{const mo=r.date?r.date.slice(0,7):'';return``}).join('')}
NoDateMonthCategoryBill InfoAmountStatus
${r.no} ${r.date} ${MLF[mo]||mo} ${mo?mo.slice(0,4):''} ${getR(r).catLabel||getR(r).cat||'โ€”'} ${r.billInfo||'โ€”'} RM ${fmt(getR(r).submittedAmt)} ${statusBadge(r)}
TOTALRM ${fmt(total)}
`; document.getElementById('mo').classList.add('show'); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ STAFF PROFILES โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function staffProfilesPage(){ const active=HR_EMPS.filter(e=>!e.resigned).length; const resigned=HR_EMPS.filter(e=>e.resigned).length; return`
${kpi('blue','Total Staff',''+HR_EMPS.length)}${kpi('green','Active',''+active)}${kpi('red','Resigned',''+resigned)}${kpi('yellow','Total Positions',[...new Set(HR_EMPS.map(e=>e.position).filter(Boolean))].length+'')}
Emp NoNameIC No.EPF No.Tax No.PhonePositionBank Account No.BankStatus
`; } function filterStaff(q){ const st=document.getElementById('spst')?.value||'active';const sq=(q||'').toLowerCase(); const list=HR_EMPS.filter(e=>{if(st==='active'&&e.resigned)return false;if(st==='resigned'&&!e.resigned)return false;if(sq&&![e.name,e.empNo,e.position,e.ic,e.phone,e.epfNo,e.taxNo].join(' ').toLowerCase().includes(sq))return false;return true;}); const n=document.getElementById('spn');if(n)n.textContent=list.length+' employees'; const tb=document.getElementById('spb');if(!tb)return; tb.innerHTML=list.map(e=>` ${e.empNo} ${e.name} ${e.ic||'โ€”'} ${e.epfNo||'โ€”'} ${e.taxNo||'โ€”'} ${e.phone||'โ€”'} ${e.position||'โ€”'} ${e.bankAccount||'โ€”'} ${e.bank||'โ€”'} ${e.resigned?`Resigned${e.resignDate?''+e.resignDate+'':''}` :'Active'} `).join(''); } // โ”€โ”€ Staff Profile Modal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ let _spEmpNo='',_spEditing=false,_spTab='info'; const SP_FIELDS=[ {key:'name',label:'Full Name'},{key:'ic',label:'IC / Passport No.',mono:true},{key:'dob',label:'Date of Birth'}, {key:'phone',label:'Contact No.'},{key:'email',label:'Email'},{key:'address',label:'Residential Address',full:true}, {key:'emergencyContact',label:'Emergency Contact'},{key:'emergencyRelation',label:'Relationship'}, {key:'taxNo',label:'Income Tax No.',mono:true},{key:'epfNo',label:'EPF No.',mono:true}, {key:'bankAccount',label:'Bank Account No.',mono:true},{key:'bank',label:'Bank'}, {key:'position',label:'Position'},{key:'maritalStatus',label:'Marital Status'}, {key:'nationality',label:'Nationality'},{key:'resigned',label:'Status',type:'bool'}, {key:'resignDate',label:'Resignation Date',type:'date'}, ]; const SP_LEAVE_FIELDS=[ {key:'confirmDate',label:'Date of Confirmation',type:'date'}, {key:'entType',label:'Entitlement Type',type:'select',opts:['unlimited','standard']}, {key:'annualDays',label:'Annual Leave (days/year)',type:'number'}, {key:'carryOver2026',label:'Carry Over 2026 (days)',type:'number'}, {key:'leaveRemarks',label:'Leave Remarks'}, ]; function openStaffProfile(empNo){_spEmpNo=empNo;_spEditing=false;_spTab='info';document.getElementById('mt').textContent='Employee Profile';renderStaffModal();document.getElementById('mo').classList.add('show');} function renderStaffModal(){ const e=HR_EMPS.find(x=>x.empNo===_spEmpNo);if(!e)return; const lv=calcLeave(e,2026); const tabs=`
๐Ÿ“‹ Profile
๐Ÿ“„ Leave History
`; const header=`
${e.name.charAt(0)}
${e.name} ${e.resigned?'Resigned':'Active'}
${e.empNo} ยท ${e.position||'โ€”'} ยท ${e.maritalStatus||'โ€”'}
`; let body=''; if(_spTab==='info'){ const entitled=lv.entitled===null?'Unlimited':lv.entitled; const balance=lv.alBalance===null?'Unlimited':lv.alBalance; const balColor=typeof balance==='number'?(balance<0?'var(--red)':balance<=2?'var(--yellow)':'var(--green)'):'var(--teal)'; if(_spEditing){ body=`
Personal Information
Full Name
Nationality
IC / Passport No.
Date of Birth
Contact No.
Email
Residential Address
Emergency Contact
Relationship
Marital Status
Position
Financial / Payroll
Income Tax No.
EPF No.
Bank
Bank Account No.
Employment
Date of Confirmation
Leave Entitlement
Annual Leave Days / Year
Carry Over 2026 (days)
Leave Remarks
Resigned
Resignation Date
`; } else { body=`
Personal Information
Full Name
${pval(e.name)}
Nationality
${pval(e.nationality)}
IC / Passport No.
${pval(e.ic,true)}
Date of Birth
${pval(e.dob)}
Contact No.
${pval(e.phone)}
Email
${pval(e.email)}
Residential Address
${pval(e.address)}
Emergency Contact
${pval(e.emergencyContact)}
Relationship
${pval(e.emergencyRelation)}
Marital Status
${pval(e.maritalStatus)}
Position
${pval(e.position)}
Financial / Payroll
Income Tax No.
${pval(e.taxNo,true)}
EPF No.
${pval(e.epfNo,true)}
Bank
${pval(e.bank)}
Bank Account No.
${pval(e.bankAccount,true)}
Employment
Date of Confirmation
${pval(e.confirmDate)}
Resignation Date
${pval(e.resignDate)}
Leave Entitlement Type
${pval(e.entType)}
Annual Leave (days/year)
${pval(e.annualDays)}
Carry Over 2026
${pval(e.carryOver2026)}
Leave Remarks
${pval(e.leaveRemarks)}
2026 Leave Balance
Annual Leave
Entitled: ${entitled===null?'Unlimited':entitled}Used: ${lv.alUsed}Remaining: ${balance===null?'Unlimited':balance}
${typeof entitled==='number'&&entitled>0?`
`:''}
Medical / Hospital Leave
Used: ${lv.mcUsed} days
Unpaid Leave
Used: ${lv.unpaidUsed} days
Urgent Leave
Used: ${lv.urgentUsed} days
`; } } else { // Leave history tab const allYears=[...new Set(HR_LEAVES.map(l=>l.year||new Date(l.startDate).getFullYear()))].sort((a,b)=>b-a); const selYear=parseInt(document.getElementById('sp_hYear')?.value)||2026; const empUpper=e.name.toUpperCase(); const history=HR_LEAVES.filter(l=>{const ly=l.year||new Date(l.startDate).getFullYear();return ly===selYear&&normName(l.empName)===empUpper;}).sort((a,b)=>a.startDate>b.startDate?1:-1); const showForm=document.getElementById('sp_addForm')?.dataset.show==='1'; body=`
${history.length} records
${history.map(l=>``).join('')||``}
Start DateEnd DateLeave TypeDaysRemarks
${l.startDate}${l.endDate||l.startDate} ${l.type} ${l.days} ${l.remarks||'โ€”'}
No leave records for ${selYear}
`; } document.getElementById('mb').innerHTML=header+tabs+body; } function showAddLeaveForm(empNo){ const f=document.getElementById('sp_addForm');if(!f)return; const today=new Date().toISOString().slice(0,10); f.dataset.show='1';f.style.display='block'; f.innerHTML=`
Add Leave Record
`; } function autoCalcDays(){ const s=document.getElementById('al_start')?.value;const e=document.getElementById('al_end')?.value; if(s&&e){const diff=(new Date(e)-new Date(s))/(1000*60*60*24)+1;if(diff>0){const d=document.getElementById('al_days');if(d)d.value=diff;}} } function saveLeave(empNo){ const emp=HR_EMPS.find(x=>x.empNo===empNo);if(!emp)return; const start=document.getElementById('al_start')?.value;const end=document.getElementById('al_end')?.value; const type=document.getElementById('al_type')?.value;const days=parseFloat(document.getElementById('al_days')?.value||0); const remarks=document.getElementById('al_remarks')?.value.trim()||''; if(!start||!type||!days){toast('Please fill all required fields','var(--red)');return;} const year=new Date(start).getFullYear(); const id='L'+Date.now(); HR_LEAVES.push({id,empName:emp.name.toUpperCase(),startDate:start,endDate:end||start,type,days,year,remarks}); saveHRLeaves();_spTab='history';renderStaffModal();toast('โœ… Leave record added'); } function deleteLeave(id){ if(!confirm('Delete this leave record?'))return; const idx=HR_LEAVES.findIndex(l=>l.id===id);if(idx>=0)HR_LEAVES.splice(idx,1); saveHRLeaves();renderStaffModal();toast('๐Ÿ—‘๏ธ Deleted','var(--red)'); } function saveStaffProfile(){ const idx=HR_EMPS.findIndex(x=>x.empNo===_spEmpNo);if(idx<0)return; const e=HR_EMPS[idx]; const textFields=['name','nationality','ic','dob','phone','email','address','emergencyContact','emergencyRelation','maritalStatus','position','taxNo','epfNo','bank','bankAccount','confirmDate','leaveRemarks']; textFields.forEach(k=>{const el=document.getElementById('sp_'+k);if(el)e[k]=el.value.trim();}); ['annualDays','carryOver2026'].forEach(k=>{const el=document.getElementById('sp_'+k);if(el)e[k]=parseFloat(el.value)||0;}); const et=document.getElementById('sp_entType');if(et)e.entType=et.value; const res=document.getElementById('sp_resigned');if(res)e.resigned=res.checked; const rd=document.getElementById('sp_resignDate');if(rd)e.resignDate=rd.value; saveHREmps();_spEditing=false;renderStaffModal();filterStaff(document.getElementById('spq')?.value||'');toast('โœ… Saved'); } function openAddEmployee(){ document.getElementById('mt').textContent='Add New Employee'; document.getElementById('mb').innerHTML=`
Emp No *
Full Name *
IC No.
Date of Birth
Phone
Email
Residential Address
Position
Bank
Bank Account No.
EPF No.
Income Tax No.
Date of Confirmation
Annual Leave Entitlement
AL Days / Year
Carry Over Days
`; document.getElementById('mo').classList.add('show'); } function createEmployee(){ const empNo=document.getElementById('ne_empNo')?.value.trim();const name=document.getElementById('ne_name')?.value.trim(); if(!empNo||!name){toast('Emp No and Name required','var(--red)');return;} if(HR_EMPS.find(e=>e.empNo===empNo)){toast('Emp No already exists','var(--red)');return;} const e={empNo,name:name.toUpperCase(),ic:document.getElementById('ne_ic')?.value||'',dob:document.getElementById('ne_dob')?.value||'',phone:document.getElementById('ne_phone')?.value||'',email:document.getElementById('ne_email')?.value||'',address:document.getElementById('ne_address')?.value||'',position:document.getElementById('ne_position')?.value||'',bank:document.getElementById('ne_bank')?.value||'',bankAccount:document.getElementById('ne_bankAccount')?.value||'',epfNo:document.getElementById('ne_epfNo')?.value||'',taxNo:document.getElementById('ne_taxNo')?.value||'',nationality:'Malaysian',maritalStatus:'',emergencyContact:'',emergencyRelation:'',resignDate:'',resigned:false,confirmDate:document.getElementById('ne_confirmDate')?.value||'',entType:document.getElementById('ne_entType')?.value||'standard',annualDays:parseFloat(document.getElementById('ne_annualDays')?.value)||10,carryOver2026:parseFloat(document.getElementById('ne_carryOver2026')?.value)||0,leaveRemarks:''}; HR_EMPS.push(e);saveHREmps();closeModal();filterStaff(document.getElementById('spq')?.value||'');toast('โœ… Employee added'); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ LEAVE MANAGEMENT โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• let _lvYear=2026; function leaveMgmtPage(){ return`

Leave Management

${[2025,2026].map(y=>``).join('')}
Emp NoNameStatusAL EntitledAL UsedAL RemainingMC / HL UsedUnpaidUrgent
`; } function renderLeaveTable(){ const q=(document.getElementById('lvq')?.value||'').toLowerCase(); const st=document.getElementById('lvst')?.value||'active'; const list=HR_EMPS.filter(e=>{if(st==='active'&&e.resigned)return false;if(st==='resigned'&&!e.resigned)return false;if(q&&![e.name,e.empNo,e.position].join(' ').toLowerCase().includes(q))return false;return true;}); let totalALUsed=0,totalMC=0,totalUnpaid=0,onLeaveToday=0; const today=new Date().toISOString().slice(0,10); const rows=list.map(e=>{ const lv=calcLeave(e,_lvYear); totalALUsed+=lv.alUsed;totalMC+=lv.mcUsed;totalUnpaid+=lv.unpaidUsed; const onLeave=lv.empLeaves.some(l=>l.startDate<=today&&(l.endDate||l.startDate)>=today); if(onLeave)onLeaveToday++; return{e,lv,onLeave}; }); const kpiEl=document.getElementById('lvKpi'); if(kpiEl)kpiEl.innerHTML=`${kpi('blue','Active Staff',''+HR_EMPS.filter(e=>!e.resigned).length)}${kpi('red','AL Used (YTD)',''+totalALUsed+' days')}${kpi('yellow','MC/HL Used',''+totalMC+' days')}${kpi('teal','On Leave Today',''+onLeaveToday)}`; const tb=document.getElementById('lvb');if(!tb)return; tb.innerHTML=rows.map(({e,lv,onLeave})=>{ const entitled=lv.entitled===null?'Unlimited':lv.entitled; const balance=lv.alBalance===null?'Unlimited':lv.alBalance; const balColor=typeof balance==='number'?(balance<0?'var(--red)':balance<=2?'var(--yellow)':'var(--green)'):'var(--teal)'; return` ${e.empNo} ${e.name}${onLeave?' On Leave':''} ${e.resigned?'Resigned':'Active'} ${entitled} ${lv.alUsed||0} ${balance} ${lv.mcUsed||0} ${lv.unpaidUsed||0} ${lv.urgentUsed||0} `; }).join(''); } function openLeaveDetail(empNo){ _spEmpNo=empNo;_spEditing=false;_spTab='history'; const e=HR_EMPS.find(x=>x.empNo===empNo); document.getElementById('mt').textContent=(e?e.name+' โ€” ':'')+'Leave Detail'; renderStaffModal(); document.getElementById('mo').classList.add('show'); } function closeModal(){document.getElementById('mo').classList.remove('show');const md=document.getElementById('md');if(md)md.style.maxWidth='860px';} // โ”€โ”€ BroadcastChannel live sync between admin and readonly tabs โ”€โ”€ (function(){ const _bc=new BroadcastChannel('inzii_sync_v1'); if(READONLY){ document.body.classList.add('readonly'); // Show loading state const _showWaiting=()=>{ const c=document.getElementById('content'); if(c)c.innerHTML='
โณ
Syncing data from INZII appโ€ฆ
Keep the main INZII app open in another tab. Or use Export View to get a shareable file.
'; }; _showWaiting(); // Request data from any open admin tab _bc.postMessage({type:'ro_request'}); _bc.onmessage=(e)=>{ if(e.data&&e.data.type==='ro_data'){ QUOT_LIST=e.data.ql||[]; ACC_TXNS=e.data.at||[]; if(e.data.qs)Object.assign(QUOT_SETTINGS,e.data.qs); nav('qt_projects',document.querySelector('.nav-item[onclick*="qt_projects"]')); } }; // Also listen for storage events (same-origin Chrome) window.addEventListener('storage',(e)=>{ if(e.key==='inzii_quotations'&&e.newValue){QUOT_LIST=JSON.parse(e.newValue||'[]');nav(_curPage,document.querySelector('.nav-item.active'));} if(e.key==='inzii_acc_txns'&&e.newValue){ACC_TXNS=JSON.parse(e.newValue||'[]');nav(_curPage,document.querySelector('.nav-item.active'));} }); // If data already in localStorage (same browser), use it immediately if(QUOT_LIST.length>0||ACC_TXNS.length>0){ nav('qt_projects',document.querySelector('.nav-item[onclick*="qt_projects"]')); } // Retry request after short delay in case admin tab needs a moment setTimeout(()=>{ _bc.postMessage({type:'ro_request'}); if(QUOT_LIST.length===0){ // Still empty after 3s โ€” show hint setTimeout(()=>{ if(QUOT_LIST.length===0)_showWaiting(); },3000); } },500); }else{ nav('staffprofiles',document.querySelector('.nav-item.active')); // Respond to readonly tab requests _bc.onmessage=(e)=>{ if(e.data&&e.data.type==='ro_request'){ _bc.postMessage({type:'ro_data',ql:QUOT_LIST,at:ACC_TXNS,qs:{companyName:QUOT_SETTINGS.companyName,companyReg:QUOT_SETTINGS.companyReg}}); } }; // Push updates to any open readonly tab when data changes window._bcPushRO=()=>_bc.postMessage({type:'ro_data',ql:QUOT_LIST,at:ACC_TXNS,qs:{companyName:QUOT_SETTINGS.companyName,companyReg:QUOT_SETTINGS.companyReg}}); } })(); // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ PAYSLIP MODULE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• const LOGO_SVG = ''; const CO = {name:'INZII DESIGN STUDIO PLT',addr1:'No.05-01, Jalan Molek 3/20, Taman Molek,',addr2:'81100 Johor Bahru, Johor, Malaysia',phone:'+60 16-7365548',email:'kavynliew@inziidesign.com'}; const PP_LIST = [ {label:'January 2026',short:"JAN'2026",start:'2026-01-01',end:'2026-01-31',days:26}, {label:'February 2026',short:"FEB'2026",start:'2026-02-01',end:'2026-02-28',days:24}, {label:'March 2026',short:"MAR'2026",start:'2026-03-01',end:'2026-03-31',days:27}, {label:'April 2026',short:"APR'2026",start:'2026-04-01',end:'2026-04-30',days:26}, {label:'May 2026',short:"MAY'2026",start:'2026-05-01',end:'2026-05-31',days:26}, {label:'June 2026',short:"JUN'2026",start:'2026-06-01',end:'2026-06-30',days:26}, {label:'July 2026',short:"JUL'2026",start:'2026-07-01',end:'2026-07-31',days:27}, {label:'August 2026',short:"AUG'2026",start:'2026-08-01',end:'2026-08-31',days:26}, {label:'September 2026',short:"SEP'2026",start:'2026-09-01',end:'2026-09-30',days:26}, {label:'October 2026',short:"OCT'2026",start:'2026-10-01',end:'2026-10-31',days:27}, {label:'November 2026',short:"NOV'2026",start:'2026-11-01',end:'2026-11-30',days:26}, {label:'December 2026',short:"DEC'2026",start:'2026-12-01',end:'2026-12-31',days:27}, ]; const DEFAULT_PS_LIST=[{"id":"PS-JAN2026-INZS0001","empNo":"INZS0001","empName":"LIEW WEI SOON","ic":"920328-01-5997","epfNo":"19194806","taxNo":"IG 25114169010","department":"MANAGEMENT","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":10000.0}],"ded":{"epf":1100.0,"socso":29.75,"eis":11.9,"tax":929.2,"unpaid":0},"emp":{"epf":1300.0,"socso":104.15,"eis":11.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":10000.0,"totalDeductions":2070.85,"netPay":7929.15,"status":"Approved"},{"id":"PS-JAN2026-INZS0007","empNo":"INZS0007","empName":"LIM WEI NI","ic":"950815-08-6044","epfNo":"22285001","taxNo":"IG 24184785000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":16.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":484.35,"netPay":3515.65,"status":"Approved"},{"id":"PS-JAN2026-INZS0009","empNo":"INZS0009","empName":"LEE JING WEN","ic":"951003-01-7136","epfNo":"20420562","taxNo":"IG 57785836100","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"COMMISSION","amount":150.0,"remark":"PJ1074 - Deisgn Commission"},{"desc":"COMMISSION","amount":1628.9,"remark":"PJ1067 - Construction Commission Balance"}],"ded":{"epf":548.0,"socso":24.75,"eis":9.9,"tax":108.75,"unpaid":0},"emp":{"epf":648.0,"socso":86.65,"eis":9.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4978.9,"totalDeductions":691.4,"netPay":4287.5,"status":"Approved"},{"id":"PS-JAN2026-INZS0013","empNo":"INZS0013","empName":"WONG KHANG CHENG","ic":"010629-01-1313","epfNo":"21968240","taxNo":"IG 40373401000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"12","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":16.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 12/01/2026-23/01/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":484.35,"netPay":3515.65,"status":"Approved"},{"id":"PS-JAN2026-INZS0015","empNo":"INZS0015","empName":"LIM QIAN WEN","ic":"920312-01-5642","epfNo":"20586617","taxNo":"IG 22423759040","department":"ADMINISTRATION","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"19","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":13.64,"remark":"PJ1062 Project Incentive"},{"desc":"INCENTIVE / BONUS","amount":1200.0,"remark":"Marketing Incentive"},{"desc":"INCENTIVE / BONUS","amount":219.69,"remark":"PJ1070 - Project Incentive"},{"desc":"INCENTIVE / BONUS","amount":225.95,"remark":"PJ1067 - Project Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":170.05,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 01/01/2026 - 02/01/2026","ANNUAL LEAVE: 12/01/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5659.28,"totalDeductions":637.7,"netPay":5021.58,"status":"Approved"},{"id":"PS-JAN2026-INZS0016","empNo":"INZS0016","empName":"CHONG WEE SHENG","ic":"981119-01-7311","epfNo":"22252270","taxNo":"IG 56672303040","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"COMMISSION","amount":136.4,"remark":"PJ1062 INZ-QUO-00281 (R0) Construction Commission"},{"desc":"COMMISSION","amount":1536.9,"remark":"PJ1070 - Construction Commission Balance"}],"ded":{"epf":627.0,"socso":28.25,"eis":11.3,"tax":171.6,"unpaid":0},"emp":{"epf":741.0,"socso":98.85,"eis":11.3},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5673.3,"totalDeductions":838.15,"netPay":4835.15,"status":"Approved"},{"id":"PS-JAN2026-INZS0017","empNo":"INZS0017","empName":"LIM HONG MIN","ic":"910613-01-6420","epfNo":"19841713","taxNo":"IG 22253139080","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"20","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3500.0},{"desc":"INCENTIVE / BONUS","amount":500.0,"remark":"PETROL ALLOWANCE"},{"desc":"COMMISSION","amount":136.4,"remark":"PJ1062 INZ-QUO-00281 (R0) Construction Commission"},{"desc":"COMMISSION","amount":1536.9,"remark":"PJ1070 - Construction Commission Balance"}],"ded":{"epf":605.0,"socso":27.25,"eis":10.9,"tax":151.6,"unpaid":181.82},"emp":{"epf":715.0,"socso":95.35,"eis":10.9},"leaveNotes":["URGENT LEAVE: 13/01/2026","UNPAID LEAVE: 21/01/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5673.3,"totalDeductions":976.57,"netPay":4696.73,"status":"Approved"},{"id":"PS-JAN2026-INZS0019","empNo":"INZS0019","empName":"TAN JING TING","ic":"020126-01-0748","epfNo":"25024966","taxNo":"IG 57099037080","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"19","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":2600.0}],"ded":{"epf":286.0,"socso":12.75,"eis":5.1,"tax":0.0,"unpaid":0},"emp":{"epf":338.0,"socso":44.65,"eis":5.1},"leaveNotes":["MEDICAL LEAVE: 05/01/2026","ANNUAL LEAVE: 23/01/2026-26/01/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":2600.0,"totalDeductions":303.85,"netPay":2296.15,"status":"Approved"},{"id":"PS-JAN2026-INZS0020","empNo":"INZS0020","empName":"CHAN WAN TENG","ic":"001212-14-1564","epfNo":"","taxNo":"","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0}],"ded":{"epf":352.0,"socso":15.75,"eis":6.3,"tax":0.0,"unpaid":0},"emp":{"epf":416.0,"socso":55.15,"eis":6.3},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":3200.0,"totalDeductions":374.05,"netPay":2825.95,"status":"Approved"},{"id":"PS-JAN2026-INZS0021","empNo":"INZS0021","empName":"JANE YAP XING YI","ic":"890328-01-6290","epfNo":"18141990","taxNo":"IG21721665100","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"January 2026","periodShort":"JAN'2026","periodStart":"2026-01-01","periodEnd":"2026-01-31","issueDate":"2026-02-07","wdWorked":"15","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"INCENTIVE / BONUS","amount":400.0,"remark":"TRANSPORT ALLOWANCE"},{"desc":"COMMISSION","amount":1628.9,"remark":"PJ1067 - Construction Commission Balance"}],"ded":{"epf":561.0,"socso":25.25,"eis":10.1,"tax":113.95,"unpaid":163.64},"emp":{"epf":663.0,"socso":88.35,"eis":10.1},"leaveNotes":["ANNUAL LEAVE: 19/01/2026 - 26/01/2026","UNPAID LEAVE: 27/01/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5228.9,"totalDeductions":873.94,"netPay":4354.96,"status":"Approved"},{"id":"PS-FEB2026_INZS0001","empNo":"INZS0001","empName":"LIEW WEI SOON","ic":"920328-01-5997","epfNo":"19194806","taxNo":"IG 25114169010","department":"MANAGEMENT","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":10000.0},{"desc":"INCENTIVE / BONUS","amount":5000.0,"remark":"Special Incentive"}],"ded":{"epf":1100.0,"socso":29.75,"eis":11.9,"tax":929.2,"unpaid":0},"emp":{"epf":1300.0,"socso":104.15,"eis":11.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":15000.0,"totalDeductions":2070.85,"netPay":12929.15,"status":"Approved"},{"id":"PS-FEB2026_INZS0007","empNo":"INZS0007","empName":"LIM WEI NI","ic":"950815-08-6044","epfNo":"22285001","taxNo":"IG 24184785000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":2000.0,"remark":"Special Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":16.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":6000.0,"totalDeductions":484.35,"netPay":5515.65,"status":"Approved"},{"id":"PS-FEB2026_INZS0009","empNo":"INZS0009","empName":"LEE JING WEN","ic":"951003-01-7136","epfNo":"20420562","taxNo":"IG 57785836100","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":235.53},{"desc":"INCENTIVE / BONUS","amount":1600.0,"remark":"Special Incentive"}],"ded":{"epf":0,"socso":0,"eis":0,"tax":0,"unpaid":0},"emp":{"epf":0.0,"socso":0.0,"eis":0.0},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":1835.53,"totalDeductions":0.0,"netPay":1835.53,"status":"Approved"},{"id":"PS-FEB2026_INZS0013","empNo":"INZS0013","empName":"WONG KHANG CHENG","ic":"010629-01-1313","epfNo":"21968240","taxNo":"IG 40373401000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"17","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":2000.0,"remark":"Special Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":16.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 23/02/2026","MEDICAL LEAVE: 26/2/2026 - 27/2/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":6000.0,"totalDeductions":484.35,"netPay":5515.65,"status":"Approved"},{"id":"PS-FEB2026_INZS0015","empNo":"INZS0015","empName":"LIM QIAN WEN","ic":"920312-01-5642","epfNo":"20586617","taxNo":"IG 22423759040","department":"ADMINISTRATION","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":2000.0,"remark":"Special Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":48.15,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":6000.0,"totalDeductions":515.8,"netPay":5484.2,"status":"Approved"},{"id":"PS-FEB2026_INZS0016","empNo":"INZS0016","empName":"CHONG WEE SHENG","ic":"981119-01-7311","epfNo":"22252270","taxNo":"IG 56672303040","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"19","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"COMMISSION","amount":1687.5,"remark":"PJ1062 - Design Commission"},{"desc":"INCENTIVE / BONUS","amount":2000.0,"remark":"Special Incentive"}],"ded":{"epf":627.0,"socso":28.25,"eis":11.3,"tax":173.15,"unpaid":0},"emp":{"epf":741.0,"socso":98.85,"eis":11.3},"leaveNotes":["ANNUAL LEAVE: 13/2/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":7687.5,"totalDeductions":839.7,"netPay":6847.8,"status":"Approved"},{"id":"PS-FEB2026_INZS0017","empNo":"INZS0017","empName":"LIM HONG MIN","ic":"910613-01-6420","epfNo":"19841713","taxNo":"IG 22253139080","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"15","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":3500.0},{"desc":"INCENTIVE / BONUS","amount":500.0,"remark":"PETROL ALLOWANCE"},{"desc":"INCENTIVE / BONUS","amount":1750.0,"remark":"Special Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":48.9,"unpaid":0.0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["MEDICAL LEAVE: 23/2/2026-27/2/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5750.0,"totalDeductions":516.55,"netPay":5233.45,"status":"Approved"},{"id":"PS-FEB2026_INZS0019","empNo":"INZS0019","empName":"TAN JING TING","ic":"020126-01-0748","epfNo":"25024966","taxNo":"IG 57099037080","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":2600.0},{"desc":"INCENTIVE / BONUS","amount":1300.0,"remark":"Special Incentive"}],"ded":{"epf":286.0,"socso":12.75,"eis":5.1,"tax":0.0,"unpaid":0},"emp":{"epf":338.0,"socso":44.65,"eis":5.1},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":3900.0,"totalDeductions":303.85,"netPay":3596.15,"status":"Approved"},{"id":"PS-FEB2026_INZS0020","empNo":"INZS0020","empName":"CHAN WAN TENG","ic":"001212-14-1564","epfNo":"","taxNo":"","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"19","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"INCENTIVE / BONUS","amount":1600.0,"remark":"Special Incentive"}],"ded":{"epf":352.0,"socso":15.75,"eis":6.3,"tax":0.0,"unpaid":0},"emp":{"epf":416.0,"socso":55.15,"eis":6.3},"leaveNotes":["ANNUAL LEAVE: 23/02/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4800.0,"totalDeductions":374.05,"netPay":4425.95,"status":"Approved"},{"id":"PS-FEB2026_INZS0021","empNo":"INZS0021","empName":"JANE YAP XING YI","ic":"890328-01-6290","epfNo":"18141990","taxNo":"IG21721665100","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"February 2026","periodShort":"FEB'2026","periodStart":"2026-02-01","periodEnd":"2026-02-28","issueDate":"2026-03-07","wdWorked":"18","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"INCENTIVE / BONUS","amount":400.0,"remark":"TRANSPORT ALLOWANCE"},{"desc":"COMMISSION","amount":235.53,"remark":"PJ1074 - Construction First Commission"},{"desc":"INCENTIVE / BONUS","amount":1600.0,"remark":"Special Incentive"}],"ded":{"epf":423.0,"socso":19.25,"eis":7.7,"tax":0.0,"unpaid":0.0},"emp":{"epf":500.0,"socso":67.35,"eis":7.7},"leaveNotes":["MEDICAL LEAVE: 25/02/2026 - 26/02/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5435.53,"totalDeductions":449.95,"netPay":4985.58,"status":"Approved"},{"id":"PS-MAR2026_INZS0001","empNo":"INZS0001","empName":"LIEW WEI SOON","ic":"920328-01-5997","epfNo":"19194806","taxNo":"IG 25114169010","department":"MANAGEMENT","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"21","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":10000.0}],"ded":{"epf":1100.0,"socso":29.75,"eis":11.9,"tax":929.2,"unpaid":0},"emp":{"epf":1300.0,"socso":104.15,"eis":11.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":10000.0,"totalDeductions":2070.85,"netPay":7929.15,"status":"Approved"},{"id":"PS-MAR2026_INZS0007","empNo":"INZS0007","empName":"LIM WEI NI","ic":"950815-08-6044","epfNo":"22285001","taxNo":"IG 24184785000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"COMMISSION","amount":2500.0,"remark":"PJ1072 Design Commission"}],"ded":{"epf":715.0,"socso":29.75,"eis":11.9,"tax":256.7,"unpaid":0},"emp":{"epf":845.0,"socso":104.15,"eis":11.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":6500.0,"totalDeductions":1013.35,"netPay":5486.65,"status":"Approved"},{"id":"PS-MAR2026_INZS0009","empNo":"INZS0009","empName":"LEE JING WEN","ic":"951003-01-7136","epfNo":"20420562","taxNo":"IG 57785836100","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"21","wdTotal":"21","earnings":[],"ded":{"epf":0,"socso":0,"eis":0,"tax":0,"unpaid":0},"emp":{"epf":0.0,"socso":0.0,"eis":0.0},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":0.0,"totalDeductions":0.0,"netPay":0.0,"status":"Approved"},{"id":"PS-MAR2026_INZS0013","empNo":"INZS0013","empName":"WONG KHANG CHENG","ic":"010629-01-1313","epfNo":"21968240","taxNo":"IG 40373401000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"COMMISSION","amount":1339.54,"remark":"PJ1077 - Project First Commission"}],"ded":{"epf":594.0,"socso":26.75,"eis":10.7,"tax":137.05,"unpaid":0},"emp":{"epf":702.0,"socso":93.65,"eis":10.7},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5339.54,"totalDeductions":768.5,"netPay":4571.04,"status":"Approved"},{"id":"PS-MAR2026_INZS0015","empNo":"INZS0015","empName":"LIM QIAN WEN","ic":"920312-01-5642","epfNo":"20586617","taxNo":"IG 22423759040","department":"ADMINISTRATION","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"20","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":48.15,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 12/3/2026-13/3/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":515.8,"netPay":3484.2,"status":"Approved"},{"id":"PS-MAR2026_INZS0016","empNo":"INZS0016","empName":"CHONG WEE SHENG","ic":"981119-01-7311","epfNo":"22252270","taxNo":"IG 56672303040","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"20","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":45.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 25/3/2026-26/3/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":513.35,"netPay":3486.65,"status":"Approved"},{"id":"PS-MAR2026_INZS0017","empNo":"INZS0017","empName":"LIM HONG MIN","ic":"910613-01-6420","epfNo":"19841713","taxNo":"IG 22253139080","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3500.0},{"desc":"INCENTIVE / BONUS","amount":500.0,"remark":"PETROL ALLOWANCE"},{"desc":"COMMISSION","amount":1116.29,"remark":"PJ1077 - Project First Commission"}],"ded":{"epf":572.0,"socso":25.75,"eis":10.3,"tax":115.9,"unpaid":0.0},"emp":{"epf":676.0,"socso":90.15,"eis":10.3},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5116.29,"totalDeductions":723.95,"netPay":4392.34,"status":"Approved"},{"id":"PS-MAR2026_INZS0019","empNo":"INZS0019","empName":"TAN JING TING","ic":"020126-01-0748","epfNo":"25024966","taxNo":"IG 57099037080","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":2600.0},{"desc":"COMMISSION","amount":185.13,"remark":"PJ1079 - Project First Commission"}],"ded":{"epf":308.0,"socso":13.75,"eis":5.5,"tax":0.0,"unpaid":0},"emp":{"epf":364.0,"socso":48.15,"eis":5.5},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":2785.13,"totalDeductions":327.25,"netPay":2457.88,"status":"Approved"},{"id":"PS-MAR2026_INZS0020","empNo":"INZS0020","empName":"CHAN WAN TENG","ic":"001212-14-1564","epfNo":"","taxNo":"","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"COMMISSION","amount":740.5,"remark":"PJ1079 - Project First Commission"},{"desc":"COMMISSION","amount":1800.0,"remark":"PJ1086 - Design Commission"}],"ded":{"epf":638.0,"socso":28.75,"eis":11.5,"tax":158.85,"unpaid":0},"emp":{"epf":754.0,"socso":100.65,"eis":11.5},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5740.5,"totalDeductions":837.1,"netPay":4903.4,"status":"Approved"},{"id":"PS-MAR2026_INZS0021","empNo":"INZS0021","empName":"JANE YAP XING YI","ic":"890328-01-6290","epfNo":"18141990","taxNo":"IG21721665100","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"March 2026","periodShort":"MAR'2026","periodStart":"2026-03-01","periodEnd":"2026-03-31","issueDate":"2026-04-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"INCENTIVE / BONUS","amount":400.0,"remark":"TRANSPORT ALLOWANCE"},{"desc":"COMMISSION","amount":771.0,"remark":"PJ1079 - Project First Commission"}],"ded":{"epf":482.0,"socso":21.75,"eis":8.7,"tax":76.4,"unpaid":0.0},"emp":{"epf":570.0,"socso":76.15,"eis":8.7},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4371.0,"totalDeductions":588.85,"netPay":3782.15,"status":"Approved"},{"id":"PS-APR2026_INZS0001","empNo":"INZS0001","empName":"LIEW WEI SOON","ic":"920328-01-5997","epfNo":"19194806","taxNo":"IG 25114169010","department":"MANAGEMENT","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":10000.0}],"ded":{"epf":1100.0,"socso":29.75,"eis":11.9,"tax":929.15,"unpaid":0},"emp":{"epf":1300.0,"socso":104.15,"eis":11.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":10000.0,"totalDeductions":2070.8,"netPay":7929.2,"status":"Approved"},{"id":"PS-APR2026_INZS0007","empNo":"INZS0007","empName":"LIM WEI NI","ic":"950815-08-6044","epfNo":"22285001","taxNo":"IG 24184785000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"16","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":200.0,"remark":"LEAD ALLOWANCE"},{"desc":"COMMISSION","amount":5572.44,"remark":"PJ1063 - Construction Second Commission"}],"ded":{"epf":1078.0,"socso":29.75,"eis":11.9,"tax":789.55,"unpaid":0},"emp":{"epf":1274.0,"socso":104.15,"eis":11.9},"leaveNotes":["ANNUAL LEAVE: 10/4/26-17/4/26"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":9772.44,"totalDeductions":1909.2,"netPay":7863.24,"status":"Approved"},{"id":"PS-APR2026_INZS0009","empNo":"INZS0009","empName":"LEE JING WEN","ic":"951003-01-7136","epfNo":"20420562","taxNo":"IG 57785836100","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"COMMISSION","amount":614.77,"remark":"PJ1074 - Construction Balance Commission"}],"ded":{"epf":69.0,"socso":0,"eis":0,"tax":0,"unpaid":0},"emp":{"epf":81.0,"socso":0.0,"eis":0.0},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":614.77,"totalDeductions":69.0,"netPay":545.77,"status":"Approved"},{"id":"PS-APR2026_INZS0013","empNo":"INZS0013","empName":"WONG KHANG CHENG","ic":"010629-01-1313","epfNo":"21968240","taxNo":"IG 40373401000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"INCENTIVE / BONUS","amount":800.0,"remark":"PETROL & CAR ALLOWANCE"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":56.65,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["Balance Annual Leave: 2.2 days"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":524.3,"netPay":3475.7,"status":"Approved"},{"id":"PS-APR2026_INZS0015","empNo":"INZS0015","empName":"LIM QIAN WEN","ic":"920312-01-5642","epfNo":"20586617","taxNo":"IG 22423759040","department":"ADMINISTRATION","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":593.6,"remark":"PJ1063 First Project Incentive"},{"desc":"INCENTIVE / BONUS","amount":85.0,"remark":"PJ1074 Project Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":88.85,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4678.6,"totalDeductions":556.5,"netPay":4122.1,"status":"Approved"},{"id":"PS-APR2026_INZS0016","empNo":"INZS0016","empName":"CHONG WEE SHENG","ic":"981119-01-7311","epfNo":"22252270","taxNo":"IG 56672303040","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"21","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":4000.0}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":45.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 30/4/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":513.35,"netPay":3486.65,"status":"Approved"},{"id":"PS-APR2026_INZS0017","empNo":"INZS0017","empName":"LIM HONG MIN","ic":"910613-01-6420","epfNo":"19841713","taxNo":"IG 22253139080","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-04-17","wdWorked":"8","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":1272.7273},{"desc":"INCENTIVE / BONUS","amount":181.8182,"remark":"PETROL ALLOWANCE"},{"desc":"COMMISSION","amount":2550.0,"remark":"PJ1062 - Commission Balance"},{"desc":"SEVERANCE PAY","amount":3500.0,"remark":"1 Month Basic Pay"}],"ded":{"epf":443.0,"socso":20.25,"eis":8.1,"tax":49.2,"unpaid":0},"emp":{"epf":523.0,"socso":70.85,"eis":8.1},"leaveNotes":["ANNUAL LEAVE: 09/04/2026-10/04/2026","LAST WORKING DAY: 10/04/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":7504.55,"totalDeductions":520.55,"netPay":6984.0,"status":"Approved"},{"id":"PS-APR2026_INZS0019","empNo":"INZS0019","empName":"TAN JING TING","ic":"020126-01-0748","epfNo":"25024966","taxNo":"IG 57099037080","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"15.5","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":2600.0},{"desc":"INCENTIVE / BONUS","amount":500.0,"remark":"PJ1077 - Project Incentive"},{"desc":"COMMISSION","amount":310.65,"remark":"PJ1079 - Construction Balance Commission"}],"ded":{"epf":322.0,"socso":14.75,"eis":5.9,"tax":0.0,"unpaid":0},"emp":{"epf":380.0,"socso":51.65,"eis":5.9},"leaveNotes":["ANNUAL LEAVE: 22/04/2026-30/04/2026","LAST WORKING DAY: 30/04/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":3410.65,"totalDeductions":342.65,"netPay":3068.0,"status":"Approved"},{"id":"PS-APR2026_INZS0020","empNo":"INZS0020","empName":"CHAN WAN TENG","ic":"001212-14-1564","epfNo":"","taxNo":"","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-05-07","wdWorked":"22","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":3200.0}],"ded":{"epf":352.0,"socso":15.75,"eis":6.3,"tax":0.0,"unpaid":0},"emp":{"epf":416.0,"socso":55.15,"eis":6.3},"leaveNotes":["Balance Annual Leave: 6.1 days"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":3200.0,"totalDeductions":374.05,"netPay":2825.95,"status":"Approved"},{"id":"PS-APR2026_INZS0021","empNo":"INZS0021","empName":"JANE YAP XING YI","ic":"890328-01-6290","epfNo":"18141990","taxNo":"IG21721665100","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"April 2026","periodShort":"APR'2026","periodStart":"2026-04-01","periodEnd":"2026-04-30","issueDate":"2026-04-17","wdWorked":"8","wdTotal":"22","earnings":[{"desc":"BASIC PAY","amount":1163.6364},{"desc":"INCENTIVE / BONUS","amount":145.4545,"remark":"TRANSPORT ALLOWANCE"}],"ded":{"epf":146.0,"socso":6.75,"eis":2.7,"tax":0.0,"unpaid":0.0},"emp":{"epf":172.0,"socso":23.65,"eis":2.7},"leaveNotes":["ANNUAL LEAVE","LAST WORKING DAY: 10/04/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":1309.09,"totalDeductions":155.45,"netPay":1153.64,"status":"Approved"},{"id":"PS-MAY2026_INZS0001","empNo":"INZS0001","empName":"LIEW WEI SOON","ic":"920328-01-5997","epfNo":"19194806","taxNo":"IG 25114169010","department":"MANAGEMENT","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":10000.0}],"ded":{"epf":1100.0,"socso":29.75,"eis":11.9,"tax":929.15,"unpaid":0},"emp":{"epf":1300.0,"socso":104.15,"eis":11.9},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":10000.0,"totalDeductions":2070.8,"netPay":7929.2,"status":"Approved"},{"id":"PS-MAY2026_INZS0007","empNo":"INZS0007","empName":"LIM WEI NI","ic":"950815-08-6044","epfNo":"22285001","taxNo":"IG 24184785000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"21","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":200.0,"remark":"LEAD ALLOWANCE"},{"desc":"COMMISSION","amount":1551.94,"remark":"PJ1078 - Construction First Commission"}],"ded":{"epf":638.0,"socso":28.75,"eis":11.5,"tax":152.75,"unpaid":0},"emp":{"epf":754.0,"socso":100.65,"eis":11.5},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":5751.94,"totalDeductions":831.0,"netPay":4920.94,"status":"Approved"},{"id":"PS-MAY2026_INZS0009","empNo":"INZS0009","empName":"LEE JING WEN","ic":"951003-01-7136","epfNo":"20420562","taxNo":"IG 57785836100","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"20","wdTotal":"20","earnings":[],"ded":{"epf":0.0,"socso":0,"eis":0,"tax":0,"unpaid":0},"emp":{"epf":0.0,"socso":0.0,"eis":0.0},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":0.0,"totalDeductions":0.0,"netPay":0.0,"status":"Approved"},{"id":"PS-MAY2026_INZS0013","empNo":"INZS0013","empName":"WONG KHANG CHENG","ic":"010629-01-1313","epfNo":"21968240","taxNo":"IG 40373401000","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"19","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"INCENTIVE / BONUS","amount":1169.0,"remark":"PETROL & CAR ALLOWANCE"}],"ded":{"epf":482.0,"socso":21.75,"eis":8.7,"tax":78.8,"unpaid":0},"emp":{"epf":570.0,"socso":76.15,"eis":8.7},"leaveNotes":["ANNUAL LEAVE: 7/5/2026 - 8/5/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4369.0,"totalDeductions":591.25,"netPay":3777.75,"status":"Approved"},{"id":"PS-MAY2026_INZS0015","empNo":"INZS0015","empName":"LIM QIAN WEN","ic":"920312-01-5642","epfNo":"20586617","taxNo":"IG 22423759040","department":"ADMINISTRATION","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"9","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":4000.0},{"desc":"INCENTIVE / BONUS","amount":413.15,"remark":"PJ1079 - Project Incentive"}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":72.95,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["MEDICAL LEAVE: 7/5/26 - 8/5/26","HOSPITAL LEAVE: 11/5/26 - 22/5/26"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4413.15,"totalDeductions":540.6,"netPay":3872.55,"status":"Approved"},{"id":"PS-MAY2026_INZS0016","empNo":"INZS0016","empName":"CHONG WEE SHENG","ic":"981119-01-7311","epfNo":"22252270","taxNo":"IG 56672303040","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"19","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":4000.0}],"ded":{"epf":440.0,"socso":19.75,"eis":7.9,"tax":45.7,"unpaid":0},"emp":{"epf":520.0,"socso":69.15,"eis":7.9},"leaveNotes":["ANNUAL LEAVE: 3/5/2026 - 4/5/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4000.0,"totalDeductions":513.35,"netPay":3486.65,"status":"Approved"},{"id":"PS-MAY2026_INZS0017","empNo":"INZS0017","empName":"LIM HONG MIN","ic":"910613-01-6420","epfNo":"19841713","taxNo":"IG 22253139080","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-17","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":4344.33}],"ded":{"epf":480.0,"socso":0.0,"eis":0.0,"tax":0.0,"unpaid":0},"emp":{"epf":567.0,"socso":0.0,"eis":0.0},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":4344.33,"totalDeductions":480.0,"netPay":3864.33,"status":"Approved"},{"id":"PS-MAY2026_INZS0019","empNo":"INZS0019","empName":"TAN JING TING","ic":"020126-01-0748","epfNo":"25024966","taxNo":"IG 57099037080","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"COMMISSION","amount":310.65,"remark":"PJ1079 - Construction Balance Commission"}],"ded":{"epf":0.0,"socso":0.0,"eis":0.0,"tax":0.0,"unpaid":0},"emp":{"epf":0.0,"socso":0.0,"eis":0.0},"leaveNotes":["ANNUAL LEAVE","LAST WORKING DAY: 30/04/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":310.65,"totalDeductions":0.0,"netPay":310.65,"status":"Approved"},{"id":"PS-MAY2026_INZS0020","empNo":"INZS0020","empName":"CHAN WAN TENG","ic":"001212-14-1564","epfNo":"","taxNo":"","department":"DESIGN","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"20","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":3200.0},{"desc":"COMMISSION","amount":1242.61,"remark":"PJ1079 - Construction Balance Commission"},{"desc":"COMMISSION","amount":2025.0,"remark":"PJ1084 - Design Commission"}],"ded":{"epf":715.0,"socso":29.75,"eis":11.9,"tax":223.8,"unpaid":0},"emp":{"epf":845.0,"socso":104.15,"eis":11.9},"leaveNotes":["ANNUAL LEAVE: 20/05/2026"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":6467.61,"totalDeductions":980.45,"netPay":5487.16,"status":"Approved"},{"id":"PS-MAY2026_INZS0021","empNo":"INZS0021","empName":"JANE YAP XING YI","ic":"890328-01-6290","epfNo":"18141990","taxNo":"IG21721665100","department":"SITE SUPERVISOR","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"20","wdTotal":"20","earnings":[{"desc":"BASIC PAY","amount":614.77},{"desc":"COMMISSION","amount":1293.28,"remark":"PJ1078 - Construction B alance Commission"},{"desc":"COMMISSION","amount":1294.39,"remark":"PJ1079 - Construction Balance Commission"}],"ded":{"epf":355.0,"socso":0.0,"eis":0.0,"tax":0.0,"unpaid":0.0},"emp":{"epf":419.0,"socso":0.0,"eis":0.0},"leaveNotes":[],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":3202.44,"totalDeductions":355.0,"netPay":2847.44,"status":"Approved"},{"id":"PS-MAY2026_INZS0022","empNo":"INZS0022","empName":"WONG KAH XUAN","ic":"040116-01-1104","epfNo":"25060754","taxNo":"IG57145967060","department":"DESIGNER","empStatus":"ACTIVE","taxStatus":"NORMAL","periodLabel":"May 2026","periodShort":"MAY'2026","periodStart":"2026-05-01","periodEnd":"2026-05-31","issueDate":"2026-06-07","wdWorked":"18","wdTotal":"21","earnings":[{"desc":"BASIC PAY","amount":2142.8571}],"ded":{"epf":238.0,"socso":10.75,"eis":4.3,"tax":0.0,"unpaid":0},"emp":{"epf":281.0,"socso":37.65,"eis":4.3},"leaveNotes":["FIRST WORKING DAY"],"leaveThisPeriod":[],"leaveBalance":null,"grossEarnings":2142.86,"totalDeductions":253.05,"netPay":1889.81,"status":"Approved"}]; const _ps_stored=JSON.parse(localStorage.getItem('inzii_payslips')||'null'); let PS_LIST=(_ps_stored&&_ps_stored.length>0)?_ps_stored:DEFAULT_PS_LIST.map(p=>({...p})); // DEFAULT always wins for its own IDs; user-created extras are kept DEFAULT_PS_LIST.forEach(dp=>{const idx=PS_LIST.findIndex(p=>p.id===dp.id);if(idx>=0){PS_LIST[idx]={...dp};}else{PS_LIST.unshift({...dp});}}); // โ”€โ”€ Migrate: INCENTIVE/BONUS with allowance remark โ†’ reclassify as allowance โ”€โ”€ (function(){ let changed=0; PS_LIST.forEach(p=>{ (p.earnings||[]).forEach(e=>{ const d=(e.desc||'').toLowerCase(); const r=(e.remark||'').toLowerCase(); if((d.includes('incentive')||d.includes('bonus'))&&r.includes('allowance')){ e.desc=(e.remark||e.desc).trim().toUpperCase(); e.remark=''; changed++; } }); }); if(changed>0){localStorage.setItem('inzii_payslips',JSON.stringify(PS_LIST));console.log('[Migration] Reclassified '+changed+' allowance earning(s)');} })(); function savePS(){localStorage.setItem('inzii_payslips',JSON.stringify(PS_LIST));} let _ps = null; // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ GMAIL API INTEGRATION โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• let GMAIL_CFG = JSON.parse(localStorage.getItem('inzii_gmail_cfg')||'{}'); // shape: { clientId, senderEmail, senderName, accessToken, tokenExpiry } function saveGmailCfg(){localStorage.setItem('inzii_gmail_cfg',JSON.stringify(GMAIL_CFG));} function gmailIsConnected(){return !!(GMAIL_CFG.accessToken&&GMAIL_CFG.tokenExpiry>Date.now());} let _gmailTC=null, _gmailPendingCB=null; function _gmailInitTC(){ if(_gmailTC)return _gmailTC; if(!GMAIL_CFG.clientId){toast('่ซ‹ๅ…ˆ่จญๅฎš Gmail Client ID๏ผˆ้ปžๆ“Š โš™๏ธ ่จญๅฎš๏ผ‰','var(--yellow)');return null;} if(typeof google==='undefined'){toast('Google API ๅฐšๆœช่ผ‰ๅ…ฅ๏ผŒ่ซ‹็ขบ่ช็ถฒ่ทฏ้€ฃ็ทš','var(--yellow)');return null;} _gmailTC=google.accounts.oauth2.initTokenClient({ client_id:GMAIL_CFG.clientId, scope:'https://www.googleapis.com/auth/gmail.send', callback:(resp)=>{ if(resp.error){ toast('Gmail ๆŽˆๆฌŠๅคฑๆ•—๏ผš'+resp.error,'var(--red)'); _gmailPendingCB&&_gmailPendingCB(null);_gmailPendingCB=null;return; } GMAIL_CFG.accessToken=resp.access_token; GMAIL_CFG.tokenExpiry=Date.now()+((+resp.expires_in||3500)-60)*1000; saveGmailCfg(); toast('โœ… Gmail ๅทฒ้€ฃ็ทš๏ผš'+GMAIL_CFG.senderEmail,'var(--green)'); _gmailPendingCB&&_gmailPendingCB(resp.access_token);_gmailPendingCB=null; _renderGmailBadge(); } }); return _gmailTC; } function gmailConnect(cb){ if(gmailIsConnected()){cb&&cb(GMAIL_CFG.accessToken);return;} const tc=_gmailInitTC();if(!tc){cb&&cb(null);return;} _gmailPendingCB=cb||null; tc.requestAccessToken({prompt:''}); } function gmailSend(to,subject,htmlBody){ return new Promise((resolve,reject)=>{ const doSend=(token)=>{ const from=`${GMAIL_CFG.senderName||CO.name} <${GMAIL_CFG.senderEmail||''}>`; const mime=[ 'MIME-Version: 1.0', `From: ${from}`, `To: ${to}`, `Subject: =?UTF-8?B?${btoa(unescape(encodeURIComponent(subject)))}?=`, 'Content-Type: text/html; charset=UTF-8', '', htmlBody ].join('\r\n'); const raw=btoa(unescape(encodeURIComponent(mime))).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,''); fetch('https://www.googleapis.com/gmail/v1/users/me/messages/send',{ method:'POST', headers:{'Authorization':'Bearer '+token,'Content-Type':'application/json'}, body:JSON.stringify({raw}) }).then(r=>r.json()).then(d=>{ if(d.error){ if(d.error.code===401){ GMAIL_CFG.accessToken=null;saveGmailCfg();_gmailTC=null; gmailConnect(t=>t?doSend(t):reject('ๆŽˆๆฌŠๅคฑๆ•—๏ผŒ่ซ‹้‡ๆ–ฐ้€ฃ็ทš')); } else { reject(d.error.message||'็™ผ้€ๅคฑๆ•—'); } } else { resolve(d); } }).catch(reject); }; if(gmailIsConnected())doSend(GMAIL_CFG.accessToken); else gmailConnect(t=>t?doSend(t):reject('ๆœช้€ฃ็ทš Gmail')); }); } function _renderGmailBadge(){ document.querySelectorAll('.gmail-badge').forEach(el=>{ el.innerHTML=gmailIsConnected() ?`โœ… ${GMAIL_CFG.senderEmail||'ๅทฒ้€ฃ็ทš'}` :`โšช Gmail ๆœช้€ฃ็ทš`; }); } function gmailSettingsModal(){ document.getElementById('gmail_settings_modal')?.remove(); const div=document.createElement('div'); div.id='gmail_settings_modal'; div.style.cssText='position:fixed;inset:0;background:rgba(35,31,32,.55);z-index:300;display:flex;align-items:center;justify-content:center'; div.onclick=e=>{if(e.target===div)div.remove();}; const connBtnHtml=gmailIsConnected() ?`` :``; div.innerHTML=`
โš™๏ธ
Gmail ็™ผ้€่จญๅฎš
่จญๅฎšๆญฅ้ฉŸ๏ผš
1. Google Cloud Console โ†’ Credentials
2. ้ธๆ“‡ไฝ ็š„ OAuth 2.0 Client ID โ†’ Authorized JavaScript origins ๅŠ ๅ…ฅ๏ผš
   ${location.origin||location.href.split('/').slice(0,3).join('/')}
3. ่ค‡่ฃฝ Client ID ่ฒผๅˆฐไธ‹ๆ–นไธฆๅ„ฒๅญ˜
${gmailIsConnected()?`โœ… ๅทฒ้€ฃ็ทš๏ผš${GMAIL_CFG.senderEmail}`:`โšช ๅฐšๆœช้€ฃ็ทš`}
${connBtnHtml}
`; document.body.appendChild(div); } function _gmailSaveSettings(){ const cid=(document.getElementById('gcfg_cid')?.value||'').trim(); const email=(document.getElementById('gcfg_email')?.value||'').trim(); const name=(document.getElementById('gcfg_name')?.value||'').trim(); if(!cid){toast('่ซ‹ๅกซๅฏซ Client ID','var(--yellow)');return;} if(!email){toast('่ซ‹ๅกซๅฏซ็™ผไปถไบบ Email','var(--yellow)');return;} if(cid!==GMAIL_CFG.clientId){_gmailTC=null;GMAIL_CFG.accessToken=null;GMAIL_CFG.tokenExpiry=0;} GMAIL_CFG.clientId=cid;GMAIL_CFG.senderEmail=email;GMAIL_CFG.senderName=name||CO.name; saveGmailCfg(); document.getElementById('gmail_settings_modal')?.remove(); toast('โœ… Gmail ่จญๅฎšๅทฒๅ„ฒๅญ˜','var(--green)'); _renderGmailBadge(); } function _gmailTestConnect(){ const cid=(document.getElementById('gcfg_cid')?.value||'').trim(); const email=(document.getElementById('gcfg_email')?.value||'').trim(); const name=(document.getElementById('gcfg_name')?.value||'').trim(); if(!cid){toast('่ซ‹ๅ…ˆๅกซๅฏซ Client ID','var(--yellow)');return;} if(cid!==GMAIL_CFG.clientId)_gmailTC=null; GMAIL_CFG.clientId=cid;GMAIL_CFG.senderEmail=email||GMAIL_CFG.senderEmail||'info@inziidesign.com';GMAIL_CFG.senderName=name||CO.name; saveGmailCfg(); const statusEl=document.getElementById('gcfg_conn'); if(statusEl)statusEl.innerHTML=`๐Ÿ”„ ้€ฃ็ทšไธญ...`; gmailConnect(t=>{ if(t&&statusEl)statusEl.innerHTML=`โœ… ๅทฒ้€ฃ็ทš๏ผš${GMAIL_CFG.senderEmail}`; else if(statusEl)statusEl.innerHTML=`โŒ ้€ฃ็ทšๅคฑๆ•—๏ผŒ่ซ‹ๆชขๆŸฅ Client ID ่ˆ‡ๆŽˆๆฌŠ่จญๅฎš`; }); } function _buildPayslipEmailHtml(p, bodyText){ // Email-safe HTML payslip (inline CSS, no print styles) const f=v=>'RM '+(+(v||0)).toLocaleString('en-MY',{minimumFractionDigits:2,maximumFractionDigits:2}); const dedRows=[ {l:'EPF / KWSP',v:p.ded?.epf},{l:'SOCSO',v:p.ded?.socso}, {l:'EIS',v:p.ded?.eis},{l:'PCB / TAX',v:p.ded?.tax}, ...(p.ded?.unpaid?[{l:'Unpaid Leave',v:p.ded.unpaid}]:[]) ].filter(d=>+(d.v||0)>0); const bodyHtml=bodyText.replace(/\n/g,'
'); return`
INZII
DESIGN STUDIO
PAYSLIP
${p.periodLabel}
${bodyHtml}
Employee
${p.empName||'โ€”'}
${p.empNo||''} ${p.department?'ยท '+p.department:''}
Pay Period
${p.periodLabel}
${p.wdWorked&&p.wdTotal?p.wdWorked+'/'+p.wdTotal+' working days':''}
Earnings
${(p.earnings||[]).filter(e=>+(e.amount||0)!==0||(e.desc==='BASIC PAY')).map(e=>`
${e.remark||e.desc} ${f(e.amount)}
`).join('')}
GROSS ${f(p.grossEarnings)}
Deductions
${dedRows.length?dedRows.map(d=>`
${d.l} ${f(d.v)}
`).join(''):'
โ€”
'}
TOTAL DED. ${f(p.totalDeductions)}
NET PAY
${f(p.netPay)}
Employer Contributions
EPF
${f(p.emp?.epf)}
SOCSO
${f(p.emp?.socso)}
EIS
${f(p.emp?.eis)}
${CO.name} ยท ${CO.phone} ยท ${CO.email}
This is a computer-generated payslip. No signature required.
`; } function payslipPage(){ return `

Payslip Generator

PeriodEmp NoEmployeeDepartmentBasicCommissionAllowanceIncentiveGrossNet PayStatus
`; } function renderPSList(){ const m=document.getElementById('psm')?.value||''; const q=(document.getElementById('psq')?.value||'').toLowerCase(); const list=PS_LIST.filter(p=>{ if(m&&p.periodLabel!==m)return false; if(q&&![p.empName,p.empNo].join(' ').toLowerCase().includes(q))return false; return true; }).sort((a,b)=>b.id>a.id?1:-1); const n=document.getElementById('psCount');if(n)n.textContent=list.length+' payslips'; const tb=document.getElementById('psb');if(!tb)return; if(!list.length){tb.innerHTML=`No payslips yet. Click "+ Generate Payslip" to start.`;return;} tb.innerHTML=list.map(p=>` ${p.periodLabel} ${p.empNo||'โ€”'} ${p.empName||'โ€”'} ${p.department||'โ€”'} ${fmt((p.earnings||[]).find(e=>e.desc==='BASIC PAY')?.amount||p.earnings?.[0]?.amount||0)} ${fmt((p.earnings||[]).filter(e=>e.desc.toLowerCase().includes('commission')).reduce((s,e)=>s+(+e.amount||0),0))} ${fmt((p.earnings||[]).filter(e=>{const d=(e.desc||'').toLowerCase();return d.includes('allowance')&&!d.includes('incentive')&&!d.includes('bonus');}).reduce((s,e)=>s+(+e.amount||0),0))} ${fmt((p.earnings||[]).filter(e=>{const d=(e.desc||'').toLowerCase();return (d.includes('incentive')||d.includes('bonus'))&&!d.includes('allowance');}).reduce((s,e)=>s+(+e.amount||0),0))} ${fmt(p.grossEarnings||0)} ${fmt(p.netPay||0)} ${p.empStatus||'ACTIVE'} `).join(''); } function openCreatePS(id){ if(id){_ps=JSON.parse(JSON.stringify(PS_LIST.find(p=>p.id===id)||{}));} else{ const today=new Date().toISOString().slice(0,10); const pp=PP_LIST.find(p=>p.label==='June 2026')||PP_LIST[5]; _ps={id:'PS-'+Date.now(),empNo:'',empName:'',ic:'',epfNo:'',taxNo:'',department:'',empStatus:'ACTIVE',taxStatus:'NORMAL', periodLabel:pp.label,periodShort:pp.short,periodStart:pp.start,periodEnd:pp.end, issueDate:today,wdWorked:pp.days+'',wdTotal:pp.days+'', earnings:[{desc:'BASIC PAY',amount:0},{desc:'COMMISSION',amount:0,remark:''},{desc:'INCENTIVE / BONUS',amount:0,remark:''}], ded:{epf:0,socso:0,eis:0,tax:0,unpaid:0}, emp:{epf:0,socso:0,eis:0}, leaveNotes:[],leaveThisPeriod:[],leaveBalance:null,grossEarnings:0,totalDeductions:0,netPay:0}; } document.getElementById('md').style.maxWidth='940px'; document.getElementById('mt').textContent=id?'Edit Payslip':'Generate Payslip'; renderPSForm(); document.getElementById('mo').classList.add('show'); } function renderPSForm(){ const p=_ps; const gross=p.earnings.reduce((s,e)=>s+(+e.amount||0),0); const td=(+p.ded.epf||0)+(+p.ded.socso||0)+(+p.ded.eis||0)+(+p.ded.tax||0)+(+p.ded.unpaid||0); const net=gross-td; document.getElementById('mb').innerHTML=`
Employee
SELECT EMPLOYEE
IC No.
EPF No.
Income Tax No.
Department
Employment Status
Tax Status
Pay Period
MONTH
Issue Date
Working Days (Worked / Total)
/ days
Employer Contributions
EPF Employer 12/13%
SOCSO Employer 1.75% (Jun 2026+)
EIS Employer 0.2%
Earnings / Income
${(()=>{const basicRows=p.earnings.filter((_,i)=>i===0);return basicRows.map((e,_)=>{const i=0;return`
`;}).join('');})()}
Commission
${p.earnings.map((e,i)=>{ if(!(e.desc||'').toLowerCase().includes('commission'))return''; return`
Remark:
`; }).join('')}
Allowance
${p.earnings.map((e,i)=>{ const _da=(e.desc||'').toLowerCase(); if(!_da.includes('allowance')||_da.includes('incentive')||_da.includes('bonus'))return''; return`
`; }).join('')}
Incentive / Bonus
${p.earnings.map((e,i)=>{ const _d=(e.desc||'').toLowerCase();if((!_d.includes('incentive')&&!_d.includes('bonus'))||(_d.includes('allowance')&&!_d.includes('incentive')&&!_d.includes('bonus')))return''; return`
Remark:
`; }).join('')} ${p.earnings.slice(1).some(e=>{const _d=(e.desc||'').toLowerCase();return!_d.includes('commission')&&!_d.includes('incentive')&&!_d.includes('bonus')&&!_d.includes('allowance');})?`
Other Earnings
${p.earnings.map((e,i)=>{ if(i===0)return''; if((e.desc||'').toLowerCase().includes('commission'))return''; if((e.desc||'').toLowerCase().includes('incentive')||(e.desc||'').toLowerCase().includes('bonus'))return''; if((e.desc||'').toLowerCase().includes('allowance'))return''; return`
`; }).join('')}`:''}
Gross Earnings ${fmt(gross)}
Deductions
่‡ชๅ‹•่จˆ็ฎ—ๆ นๆ“š๏ผšEPF Employee 11% ยท SOCSO Employee 1.25%๏ผˆPhase 1 Jun 2026+๏ผŒ็„กไธŠ้™๏ผ‰ยท EIS ๅฎ˜ๆ–น Tier ่กจ๏ผˆไธŠ้™ RM7.90 @ >RM4,000๏ผ‰ใ€‚ๅฏๆ‰‹ๅ‹•ไฟฎๆ”นใ€‚
EPF / KWSP Employee 11%
SOCSO / PERKESO 1.25% (Jun 2026+)
EIS / SIP Tier table, max RM7.90
PCB / Income Tax
Unpaid Leave Deduction
Total Deductions ${fmt(td)}
NET PAY RM ${fmt(net)}
Leave / Remarks (Optional)
${(p.leaveNotes||[]).map((n,i)=>`
`).join('')}
Leave Balance & Leave This Period
่ซ‹ๅ…ˆ้ธๆ“‡ๅ“กๅทฅๅ’Œ่–ช่ณ‡ๆœŸ้–“๏ผŒ็ณป็ตฑๅฐ‡่‡ชๅ‹•่ผ‰ๅ…ฅๅ‡ๆœŸ่จ˜้Œ„ใ€‚
${PS_LIST.find(x=>x.id===p.id)?`
`:''}
`; } // โ”€โ”€ MY Payroll Calculation Tables โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function _myEPF(gross){ // Employee 11%, Employer 13%(โ‰คRM5000)/12%(>RM5000) const emp=Math.floor(gross*0.11*100)/100; const er=parseFloat((gross*(gross>5000?0.12:0.13)).toFixed(2)); return{emp:parseFloat(emp.toFixed(2)),er}; } function _mySOCSO(gross){ // SOCSO Jun 2026 Phase 1 โ€” official table data points, linear interpolation // [salary, employee, employer] const T=[ [0,0,0],[1700,20.60,28.85],[2000,24.40,34.15],[2500,30.60,42.85], [3000,36.90,51.65],[3500,43.10,60.35],[4000,49.40,69.15], [4500,55.60,77.85],[5000,61.90,86.65],[5500,68.10,95.35],[6000,74.40,104.15] ]; const r5=v=>Math.round(v*20)/20; // round to nearest 0.05 if(gross<=0)return{emp:0,er:0}; if(gross>=6000){ // extrapolate beyond RM6,000 using last interval rate const dEmp=(74.40-68.10)/500,dEr=(104.15-95.35)/500; return{emp:parseFloat(r5(74.40+(gross-6000)*dEmp).toFixed(2)),er:parseFloat(r5(104.15+(gross-6000)*dEr).toFixed(2))}; } for(let i=0;i=lo&&gross<=hi){ const ratio=(gross-lo)/(hi-lo); return{emp:parseFloat(r5(eLo+ratio*(eHi-eLo)).toFixed(2)),er:parseFloat(r5(rLo+ratio*(rHi-rLo)).toFixed(2))}; } } return{emp:0,er:0}; } function _myEIS(gross){ // EIS official contribution table (Employee = Employer) // Source: PERKESO EIS Schedule, capped at RM4,000+ const T=[ [0,1000,0],[1000,1100,2.10],[1100,1200,2.30],[1200,1300,2.50], [1300,1400,2.70],[1400,1500,2.90],[1500,1600,3.10],[1600,1700,3.30], [1700,1800,3.50],[1800,1900,3.70],[1900,2000,3.90],[2000,2100,4.10], [2100,2200,4.30],[2200,2300,4.50],[2300,2400,4.70],[2400,2500,4.90], [2500,2600,5.10],[2600,2700,5.30],[2700,2800,5.50],[2800,2900,5.70], [2900,3000,5.90],[3000,3100,6.10],[3100,3200,6.30],[3200,3300,6.50], [3300,3400,6.70],[3400,3500,6.90],[3500,3600,7.10],[3600,3700,7.30], [3700,3800,7.50],[3800,3900,7.70],[3900,4000,7.90] ]; let contrib=7.90; // >RM4,000 capped at 7.90 for(const[lo,hi,v]of T){if(gross>lo&&gross<=hi){contrib=v;break;}} if(gross<=0)contrib=0; return{emp:contrib,er:contrib}; } function psAutoCalc(){ // Auto-calculate EPF, SOCSO, EIS from current gross earnings const gross=_ps.earnings.reduce((s,e)=>s+(+e.amount||0),0); const basic=+((_ps.earnings||[])[0]?.amount)||0; // EPF based on gross; SOCSO/EIS also gross const epf=_myEPF(gross); const soc=_mySOCSO(gross); const eis=_myEIS(gross); // Employee deductions const e1=document.getElementById('f_d_epf');if(e1)e1.value=epf.emp; const e2=document.getElementById('f_d_soc');if(e2)e2.value=soc.emp; const e3=document.getElementById('f_d_eis');if(e3)e3.value=eis.emp; // Employer contributions const e4=document.getElementById('f_e_epf');if(e4)e4.value=epf.er; const e5=document.getElementById('f_e_soc');if(e5)e5.value=soc.er; const e6=document.getElementById('f_e_eis');if(e6)e6.value=eis.er; psCalc(); const ins=Math.min(gross,5000); toast(`โšก EPF ${epf.emp} | SOCSO ${soc.emp} (1.25%) | EIS ${eis.emp} (table)`,'var(--teal)'); } function psCalc(){ const gross=_ps.earnings.reduce((s,e)=>s+(+e.amount||0),0); const epf=+document.getElementById('f_d_epf')?.value||0; const soc=+document.getElementById('f_d_soc')?.value||0; const eis=+document.getElementById('f_d_eis')?.value||0; const tax=+document.getElementById('f_d_tax')?.value||0; const unp=+document.getElementById('f_d_unp')?.value||0; const td=epf+soc+eis+tax+unp; const net=gross-td; _ps.ded={epf,socso:soc,eis,tax,unpaid:unp}; _ps.grossEarnings=gross;_ps.totalDeductions=td;_ps.netPay=net; const gv=document.getElementById('v_gross');if(gv)gv.textContent=fmt(gross); const dv=document.getElementById('v_ded');if(dv)dv.textContent=fmt(td); const nv=document.getElementById('v_net');if(nv)nv.textContent='RM '+fmt(net); } function psAutoEPF(){ const gross=_ps.earnings.reduce((s,e)=>s+(+e.amount||0),0); const empEPF=Math.round(gross*0.11*100)/100; const erEPF=Math.round(gross*(gross>5000?0.12:0.13)*100)/100; const e1=document.getElementById('f_d_epf');if(e1)e1.value=empEPF; const e2=document.getElementById('f_e_epf');if(e2)e2.value=erEPF; psCalc();toast('โšก EPF filled: Employee 11%, Employer '+(gross>5000?'12%':'13%')); } function calcWorkdays(year, month){ const dim=new Date(year,month,0).getDate(); let n=0; for(let d=1;d<=dim;d++){const dow=new Date(year,month-1,d).getDay();if(dow!==0&&dow!==6)n++;} return n; } function psSyncLeave(){ if(!_ps.empNo||!_ps.periodStart)return; const emp=HR_EMPS.find(e=>e.empNo===_ps.empNo);if(!emp)return; const pStart=_ps.periodStart,pEnd=_ps.periodEnd; const d=new Date(pStart); const year=d.getFullYear(),month=d.getMonth()+1; const totalWD=calcWorkdays(year,month); const empUpper=emp.name.toUpperCase(); _ps.leaveThisPeriod=HR_LEAVES.filter(l=>{ if(normName(l.empName)!==empUpper)return false; const ls=l.startDate,le=l.endDate||l.startDate; return ls<=pEnd&&le>=pStart; }); const unpaidDays=_ps.leaveThisPeriod.filter(l=>l.type.toLowerCase().includes('unpaid')).reduce((s,l)=>s+l.days,0); _ps.wdTotal=totalWD+''; _ps.wdWorked=(totalWD-unpaidDays)+''; const lv=calcLeave(emp,year); _ps.leaveBalance={entitled:lv.entitled,alUsed:lv.alUsed,alBalance:lv.alBalance,mcUsed:lv.mcUsed,unpaidUsed:lv.unpaidUsed,urgentUsed:lv.urgentUsed}; // sync form inputs const wdw=document.getElementById('f_wdw');if(wdw)wdw.value=_ps.wdWorked; const wdt=document.getElementById('f_wdt');if(wdt)wdt.value=_ps.wdTotal; // refresh leave section only const lsec=document.getElementById('ps_leaveSec');if(lsec)renderPSLeaveSec(); } function renderPSLeaveSec(){ const p=_ps; const lb=p.leaveBalance; const ltp=p.leaveThisPeriod||[]; const el=document.getElementById('ps_leaveSec');if(!el)return; const alEnt=lb?lb.entitled:null; const alBal=lb?lb.alBalance:null; const balColor=typeof alBal==='number'?(alBal<0?'var(--red)':alBal<=2?'var(--yellow)':'var(--green)'):'var(--teal)'; el.innerHTML=` ${lb?`
AL Entitled
${alEnt===null?'Unlimited':alEnt} days
AL Used (YTD)
${lb.alUsed} days
AL Balance
${alBal===null?'Unlimited':alBal} days
MC / HL Used
${lb.mcUsed} days
`:''}
Leave taken this period (auto-fetched from Leave Management):
${ltp.length?` ${ltp.map(l=>``).join('')}
TypeStartEndDaysRemarks
${l.type}${l.startDate}${l.endDate||l.startDate}${l.days}${l.remarks||'โ€”'}
`:`
No leave records found for this period.
`}`; } function psPickEmp(empNo){ const e=HR_EMPS.find(x=>x.empNo===empNo);if(!e)return; _ps.empNo=e.empNo;_ps.empName=e.name;_ps.ic=e.ic||''; _ps.epfNo=e.epfNo||'';_ps.taxNo=e.taxNo||''; _ps.empStatus=e.resigned?'RESIGNED':'ACTIVE'; const pos=(e.position||'').toUpperCase(); _ps.department=pos.includes('DIRECTOR')||pos.includes('MANAGE')?'MANAGEMENT':pos.includes('DESIGN')?'DESIGN':pos.includes('ADMIN')||pos.includes('HR')?'ADMINISTRATION':pos.includes('ACCOUNT')||pos.includes('FINANC')?'ACCOUNTS':e.position||''; renderPSForm(); psSyncLeave(); } function psSetPeriod(label){ const pp=PP_LIST.find(x=>x.label===label);if(!pp)return; _ps.periodLabel=pp.label;_ps.periodShort=pp.short;_ps.periodStart=pp.start;_ps.periodEnd=pp.end; const d=new Date(pp.start); const wd=calcWorkdays(d.getFullYear(),d.getMonth()+1); _ps.wdTotal=wd+'';_ps.wdWorked=wd+''; const wdwEl=document.getElementById('f_wdw');if(wdwEl)wdwEl.value=wd; const wdtEl=document.getElementById('f_wdt');if(wdtEl)wdtEl.value=wd; psSyncLeave(); } function psCollect(){ _ps.ic=document.getElementById('f_ic')?.value||''; _ps.epfNo=document.getElementById('f_epf_no')?.value||''; _ps.taxNo=document.getElementById('f_tax_no')?.value||''; _ps.department=document.getElementById('f_dept')?.value||''; _ps.empStatus=document.getElementById('f_empst')?.value||'ACTIVE'; _ps.taxStatus=document.getElementById('f_taxst')?.value||'NORMAL'; _ps.issueDate=document.getElementById('f_iss')?.value||''; _ps.wdWorked=document.getElementById('f_wdw')?.value||''; _ps.wdTotal=document.getElementById('f_wdt')?.value||''; _ps.emp={epf:+document.getElementById('f_e_epf')?.value||0,socso:+document.getElementById('f_e_soc')?.value||0,eis:+document.getElementById('f_e_eis')?.value||0}; psCalc(); } function psSaveOnly(){ psCollect(); const idx=PS_LIST.findIndex(x=>x.id===_ps.id); if(idx>=0)PS_LIST[idx]=_ps;else PS_LIST.push(_ps); savePS();renderPSList();toast('๐Ÿ’พ Payslip saved'); } function psSaveAndPrint(){ psCollect(); const idx=PS_LIST.findIndex(x=>x.id===_ps.id); if(idx>=0)PS_LIST[idx]=_ps;else PS_LIST.push(_ps); savePS();closeModal();renderPSList(); doPrintPS(_ps.id); } function duplicatePS(id){ const orig=PS_LIST.find(x=>x.id===id);if(!orig)return; const copy=JSON.parse(JSON.stringify(orig)); copy.id='PS-'+Date.now(); // Open the duplicate in edit form so user can adjust period/details before saving _ps=copy; document.getElementById('md').style.maxWidth='940px'; document.getElementById('mt').textContent='Duplicate Payslip'; renderPSForm(); document.getElementById('mo').classList.add('show'); toast('Duplicated โ€” adjust details and save','var(--accent)'); } function deletePS(id){ if(!confirm('Delete this payslip?'))return; PS_LIST=PS_LIST.filter(x=>x.id!==id); savePS();renderPSList();toast('๐Ÿ—‘๏ธ Deleted','var(--red)'); } function emailPS(id){ const p=PS_LIST.find(x=>x.id===id);if(!p){toast('Not found','var(--red)');return;} const emp=HR_EMPS.find(e=>e.empNo===p.empNo); const empEmail=emp?.email||''; const subject=`Your Payslip for ${p.periodLabel} โ€” ${CO.name}`; const body=`Dear ${p.empName},\n\nPlease find your payslip for ${p.periodLabel} below.\n\nSummary:\n Gross Earnings : RM ${(+(p.grossEarnings||0)).toLocaleString('en-MY',{minimumFractionDigits:2})}\n Total Deductions: RM ${(+(p.totalDeductions||0)).toLocaleString('en-MY',{minimumFractionDigits:2})}\n Net Pay : RM ${(+(p.netPay||0)).toLocaleString('en-MY',{minimumFractionDigits:2})}\n\nIf you have any questions, please do not hesitate to contact HR.\n\nBest regards,\n${CO.name}`; document.getElementById('ps_email_modal')?.remove(); const div=document.createElement('div'); div.id='ps_email_modal'; div.style.cssText='position:fixed;inset:0;background:rgba(35,31,32,.5);z-index:200;display:flex;align-items:center;justify-content:center'; div.onclick=e=>{if(e.target===div)div.remove();}; const hasGmail=!!(GMAIL_CFG.clientId); const senderLine=hasGmail ?`
ๅพž
` :`
โš™๏ธ ๅฐšๆœช่จญๅฎš Gmail โ€” email ๅฐ‡็”จๆœฌๅœฐ Mail App ็™ผ้€
`; div.innerHTML=`
๐Ÿ“ง
Email Payslip
${p.empName} ยท ${p.periodLabel}
${senderLine}
${!empEmail?`
โš ๏ธ ๆญคๅ“กๅทฅๆช”ๆกˆๆœชๅกซๅฏซ Email๏ผŒ่ซ‹ๆ‰‹ๅ‹•่ผธๅ…ฅ
`:''}
${hasGmail?`
ๆœช้ธๆ“‡
Payslip ๅ…งๅฎนไปฅ HTML ๆ ผๅผๅตŒๅ…ฅ Email๏ผŒๅฏๅฆๅค–้™„ไธŠ PDF ๆˆ–ๅ…ถไป–ๆช”ๆกˆ
` :''}
${hasGmail?'':``}
`; document.body.appendChild(div); // Render Gmail badge after DOM ready setTimeout(_renderGmailBadge,0); } async function psEmailSend(id){ const to=(document.getElementById('pse_to')?.value||'').trim(); const subj=(document.getElementById('pse_subj')?.value||'').trim(); const bodyText=(document.getElementById('pse_body')?.value||'').trim(); if(!to){toast('่ซ‹ๅกซๅฏซๆ”ถไปถไบบ Email','var(--yellow)');return;} if(GMAIL_CFG.clientId){ // โ”€โ”€ Gmail API: HTML email body + optional attachment โ”€โ”€ const btn=document.getElementById('pse_send_btn'); if(btn){btn.disabled=true;btn.textContent='โณ ๅ‚ณ้€ไธญ...';} try{ const p=PS_LIST.find(x=>x.id===id)||_ps; const htmlBody=_buildPayslipEmailHtml(p,bodyText); // Check for optional attachment const attachFile=document.getElementById('pse_attach')?.files?.[0]; if(attachFile){ // Read file as base64 const attachB64=await new Promise((res,rej)=>{ const r=new FileReader(); r.onload=e=>res(e.target.result.split(',')[1]); r.onerror=rej; r.readAsDataURL(attachFile); }); await _gmailSendWithAttachment(to,subj,htmlBody,attachB64,attachFile.name,attachFile.type||'application/octet-stream'); }else{ await gmailSend(to,subj,htmlBody); } document.getElementById('ps_email_modal')?.remove(); toast('โœ… Payslip ๅทฒๅพž '+GMAIL_CFG.senderEmail+' ๆˆๅŠŸ็™ผ้€','var(--green)'); }catch(e){ if(btn){btn.disabled=false;btn.textContent='๐Ÿ“ง ๅ‚ณ้€';} toast('โŒ ็™ผ้€ๅคฑๆ•—๏ผš'+e,'var(--red)'); } }else{ // โ”€โ”€ Fallback: mailto + print preview โ”€โ”€ doPrintPS(id); setTimeout(()=>{ const a=document.createElement('a'); a.href=`mailto:${encodeURIComponent(to)}?subject=${encodeURIComponent(subj)}&body=${encodeURIComponent(bodyText)}`; a.click(); document.getElementById('ps_email_modal')?.remove(); toast('Email ่‰็จฟๅทฒ้–‹ๅ•Ÿ๏ผŒ่ซ‹้™„ไธŠ PDF ๅพŒๅ‚ณ้€','var(--teal)'); },600); } } // โ”€โ”€ PAYSLIP HTML / PDF HELPERS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function _buildPayslipHtmlDoc(p){ const f=v=>(+(v||0)).toLocaleString('en-MY',{minimumFractionDigits:2,maximumFractionDigits:2}); const dedRows=[ {l:'EPF / KWSP CONTRIBUTION',v:p.ded?.epf}, {l:'SOCSO CONTRIBUTION',v:p.ded?.socso}, {l:'EIS CONTRIBUTION',v:p.ded?.eis}, {l:'TAX / PCB CONTRIBUTION',v:p.ded?.tax}, ...(p.ded?.unpaid?[{l:'UNPAID LEAVE',v:p.ded.unpaid}]:[]), ].filter(d=>d.v); const workdays=p.wdWorked&&p.wdTotal?`${p.wdWorked}/${p.wdTotal} days`:''; // build label for each earning (show remark if present) const earningLabel = e => { if(e.remark) return e.remark; return e.desc; }; const html=` Payslip โ€“ ${p.empName} โ€“ ${p.periodLabel}
${LOGO_SVG}
${CO.name}
${CO.addr1}
${CO.addr2}
Phone: ${CO.phone}  |  Email: ${CO.email}
END PAYMENT โ€“ ${p.periodShort||p.periodLabel}

EMPLOYEE NO.${p.empNo||'โ€”'}
NAME${p.empName||'โ€”'}
IC NO.${p.ic||'โ€”'}
DEPARTMENT${p.department||'โ€”'}
STATUS${p.empStatus||'ACTIVE'}
EPF NO.${p.epfNo||'โ€”'}
TAX NO.${p.taxNo||'โ€”'}
TAX STATUS${p.taxStatus||'NORMAL'}

Earnings / Income (RM)
${(p.earnings||[]).filter(e=>(+e.amount||0)!==0||(e.desc==='BASIC PAY')).map(e=>`
${earningLabel(e)}${f(e.amount)}
`).join('')}
TOTAL${f(p.grossEarnings)}
Deduction (RM)
${dedRows.map(d=>`
${d.l}${f(d.v)}
`).join('')}
TOTAL${f(p.totalDeductions)}
Others (RM)
${workdays?`
WORKING DAYS${workdays}
`:''} ${(p.leaveNotes||[]).filter(n=>n).map(n=>`
${n}
`).join('')}
NET PAYRM ${f(p.netPay)}
EMPLOYER CONTRIBUTIONS
EPF (Employer)
RM ${f(p.emp?.epf)}
SOCSO (Employer)
RM ${f(p.emp?.socso)}
EIS (Employer)
RM ${f(p.emp?.eis)}
${(()=>{ const lb=p.leaveBalance; const ltp=p.leaveThisPeriod||[]; if(!lb&&!ltp.length)return''; const alEnt=lb&&lb.entitled!==null?lb.entitled:'Unlimited'; const alBal=lb&&lb.alBalance!==null?lb.alBalance:'Unlimited'; const balColor=typeof alBal==='number'?(alBal<0?'#ef4444':alBal<=2?'#f59e0b':'#16a34a'):'#0d9488'; return`
Leave Balance & Records
${lb?`
AL Entitled
${alEnt} days
AL Used (YTD)
${lb.alUsed} days
AL Balance
${alBal} days
MC / HL Used
${lb.mcUsed} days
`:''} ${ltp.length?` ${ltp.map(l=>``).join('')}
Leave TypeStart DateEnd DateDaysRemarks
${l.type}${l.startDate}${l.endDate||l.startDate}${l.days}${l.remarks||'โ€”'}
`:lb?'
No leave taken this period.
':''}
`; })()} `; return html; } function doPrintPS(id){ const p=PS_LIST.find(x=>x.id===id)||_ps; if(!p){toast('Not found','var(--red)');return;} const html=_buildPayslipHtmlDoc(p).replace('', ``); const w=window.open('','_blank','width=820,height=950'); if(!w){toast('่ซ‹ๅ…่จฑๅฝˆๅ‡บ่ฆ–็ช—ไปฅๅˆ—ๅฐ','var(--yellow)');return;} w.document.write(html);w.document.close(); } function _loadScript(src){ return new Promise((resolve,reject)=>{ if(document.querySelector(`script[src="${src}"]`)){resolve();return;} const s=document.createElement('script'); s.src=src;s.onload=resolve;s.onerror=()=>reject(new Error('็„กๆณ•่ผ‰ๅ…ฅ๏ผš'+src)); document.head.appendChild(s); }); } async function _generatePayslipPDF(p){ // Only need jsPDF in parent; html2canvas loads inside the iframe await _loadScript('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js'); // Use the EXACT same HTML as the print version โ†’ pixel-perfect match const fullHtml=_buildPayslipHtmlDoc(p); // Hidden iframe โ€” same width as A4 landscape at 96dpi (โ‰ˆ1122px) const iframe=document.createElement('iframe'); iframe.style.cssText='position:fixed;left:-9999px;top:0;width:1122px;height:3000px;border:none;visibility:hidden;'; document.body.appendChild(iframe); try{ // Write payslip into iframe (identical to opening print window) iframe.contentDocument.open(); iframe.contentDocument.write(fullHtml); iframe.contentDocument.close(); // Override body padding to match @media print values (6px 20px) // This makes the captured content match the print output await new Promise(r=>iframe.contentDocument.readyState==='complete'?r():iframe.addEventListener('load',r)); const printStyle=iframe.contentDocument.createElement('style'); printStyle.textContent='body{padding:6px 20px!important;}'; iframe.contentDocument.head.appendChild(printStyle); // Wait for layout & fonts to settle await new Promise(r=>setTimeout(r,600)); // Load html2canvas INSIDE the iframe so it sees the correct styles await new Promise((resolve,reject)=>{ const s=iframe.contentDocument.createElement('script'); s.src='https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js'; s.onload=resolve;s.onerror=()=>reject(new Error('html2canvas ่ผ‰ๅ…ฅๅคฑๆ•—')); iframe.contentDocument.head.appendChild(s); }); await new Promise(r=>setTimeout(r,150)); // Capture iframe body โ€” same CSS context as browser print const canvas=await iframe.contentWindow.html2canvas(iframe.contentDocument.body,{ scale:2.5, useCORS:true, logging:false, backgroundColor:'#ffffff', }); // Build A4 landscape PDF const {jsPDF}=window.jspdf; const pdf=new jsPDF({orientation:'landscape',unit:'mm',format:'a4'}); const pgW=pdf.internal.pageSize.getWidth(); // 297mm const pgH=pdf.internal.pageSize.getHeight(); // 210mm const imgData=canvas.toDataURL('image/jpeg',0.95); const imgAspect=canvas.height/canvas.width; // h/w ratio const imgHatFullW=pgW*imgAspect; // height if image fills full page width if(imgHatFullW<=pgH){ // Content fits within one landscape page โ€” scale up to fill height const scale=pgH/imgHatFullW; // scale to fill height const fittedW=Math.min(pgW,pgW*scale); const fittedH=imgHatFullW*scale; const xOff=(pgW-fittedW)/2; pdf.addImage(imgData,'JPEG',xOff,0,fittedW,fittedH); }else{ // Multi-page: slice canvas row by row const pxPerPage=Math.floor(canvas.width*(pgH/pgW)); let y=0; while(y0)pdf.addPage(); const h=Math.min(pxPerPage,canvas.height-y); const slice=document.createElement('canvas'); slice.width=canvas.width;slice.height=h; slice.getContext('2d').drawImage(canvas,0,y,canvas.width,h,0,0,canvas.width,h); pdf.addImage(slice.toDataURL('image/jpeg',0.95),'JPEG',0,0,pgW,pgW*(h/canvas.width)); y+=pxPerPage; } } return pdf.output('datauristring').split(',')[1]; // base64 only }finally{ document.body.removeChild(iframe); } } function _psAttachChange(){ const f=document.getElementById('pse_attach')?.files?.[0]; const nameEl=document.getElementById('pse_attach_name'); const clearBtn=document.getElementById('pse_attach_clear'); if(f){ if(nameEl)nameEl.textContent=f.name+' ('+(f.size>1024*1024?(f.size/1024/1024).toFixed(1)+'MB':(f.size/1024).toFixed(0)+'KB')+')'; if(nameEl)nameEl.style.color='var(--accent)'; if(clearBtn)clearBtn.style.display='inline'; } } function _psAttachClear(){ const inp=document.getElementById('pse_attach'); const nameEl=document.getElementById('pse_attach_name'); const clearBtn=document.getElementById('pse_attach_clear'); if(inp)inp.value=''; if(nameEl){nameEl.textContent='ๆœช้ธๆ“‡';nameEl.style.color='var(--muted)';} if(clearBtn)clearBtn.style.display='none'; } function _gmailSendWithAttachment(to,subject,htmlBody,attachB64,attachFilename,attachMime){ return new Promise((resolve,reject)=>{ const doSend=(token)=>{ const boundary='InziiAttach_'+Date.now().toString(36); const from=`${GMAIL_CFG.senderName||CO.name} <${GMAIL_CFG.senderEmail||''}>`; const bodyEncoded=btoa(unescape(encodeURIComponent(htmlBody))); const attachWrapped=(attachB64.match(/.{1,76}/g)||[]).join('\r\n'); const safeFilename=attachFilename.replace(/[^\x20-\x7E]/g,'_'); const mime=[ 'MIME-Version: 1.0', `From: ${from}`, `To: ${to}`, `Subject: =?UTF-8?B?${btoa(unescape(encodeURIComponent(subject)))}?=`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, 'Content-Type: text/html; charset=UTF-8', 'Content-Transfer-Encoding: base64', '', bodyEncoded, '', `--${boundary}`, `Content-Type: ${attachMime}`, `Content-Disposition: attachment; filename="${safeFilename}"`, 'Content-Transfer-Encoding: base64', '', attachWrapped, '', `--${boundary}--` ].join('\r\n'); const raw=btoa(mime).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,''); fetch('https://www.googleapis.com/gmail/v1/users/me/messages/send',{ method:'POST', headers:{'Authorization':'Bearer '+token,'Content-Type':'application/json'}, body:JSON.stringify({raw}) }).then(r=>r.json()).then(d=>{ if(d.error){ if(d.error.code===401){GMAIL_CFG.accessToken=null;saveGmailCfg();_gmailTC=null;gmailConnect(t=>t?doSend(t):reject('Auth failed'));} else reject(d.error.message||'Send failed'); }else resolve(d); }).catch(reject); }; if(gmailIsConnected())doSend(GMAIL_CFG.accessToken); else gmailConnect(t=>t?doSend(t):reject('ๆœช้€ฃ็ทš Gmail')); }); } function _gmailSendWithPDF(to,subject,bodyText,pdfBase64,pdfFilename){ return new Promise((resolve,reject)=>{ const doSend=(token)=>{ const boundary='InziiPS_'+Date.now().toString(36); const from=`${GMAIL_CFG.senderName||CO.name} <${GMAIL_CFG.senderEmail||''}>`; // Encode body as base64 (handles UTF-8 / Chinese names) const bodyB64=btoa(unescape(encodeURIComponent( bodyText.replace(/</g,'<').replace(/&/g,'&').replace(/\n/g,'
') ))); // Wrap PDF base64 at 76 chars per MIME spec const pdfWrapped=(pdfBase64.match(/.{1,76}/g)||[]).join('\r\n'); // Safe ASCII filename for MIME header const safeFilename=pdfFilename.replace(/[^\x20-\x7E]/g,'_'); const mime=[ 'MIME-Version: 1.0', `From: ${from}`, `To: ${to}`, `Subject: =?UTF-8?B?${btoa(unescape(encodeURIComponent(subject)))}?=`, `Content-Type: multipart/mixed; boundary="${boundary}"`, '', `--${boundary}`, 'Content-Type: text/html; charset=UTF-8', 'Content-Transfer-Encoding: base64', '', bodyB64, '', `--${boundary}`, 'Content-Type: application/pdf', `Content-Disposition: attachment; filename="${safeFilename}"`, 'Content-Transfer-Encoding: base64', '', pdfWrapped, '', `--${boundary}--` ].join('\r\n'); // Outer base64url encode โ€” MIME is ASCII-safe at this point const raw=btoa(mime).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,''); fetch('https://www.googleapis.com/gmail/v1/users/me/messages/send',{ method:'POST', headers:{'Authorization':'Bearer '+token,'Content-Type':'application/json'}, body:JSON.stringify({raw}) }).then(r=>r.json()).then(d=>{ if(d.error){ if(d.error.code===401){ GMAIL_CFG.accessToken=null;saveGmailCfg();_gmailTC=null; gmailConnect(t=>t?doSend(t):reject('Auth failed')); }else reject(d.error.message||'Send failed'); }else resolve(d); }).catch(reject); }; if(gmailIsConnected())doSend(GMAIL_CFG.accessToken); else gmailConnect(t=>t?doSend(t):reject('ๆœช้€ฃ็ทš Gmail')); }); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ PAYROLL MONTHLY SUMMARY โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function payrollSummaryPage(){ return`

๐Ÿ“Š Monthly Payroll Summary

# Emp No Name Basic (RM) Commission (RM) Allowance (RM) Incentive (RM) Gross Earning (RM) Unpaid Leave (RM) EPF (Emp) SOCSO (Emp) EIS (Emp) Tax / PCB Total Deduction Net Pay (RM) EPF (Employer) SOCSO (Employer) EIS (Employer) Status
`; } function showPSDetail(empNo, period){ const emp = HR_EMPS.find(e=>e.empNo===empNo)||{}; const records = PS_LIST.filter(p=>p.empNo===empNo).sort((a,b)=>a.periodLabel.localeCompare(b.periodLabel)); const RM = v=>parseFloat(v||0).toLocaleString('en-MY',{minimumFractionDigits:2}); const get=(p,desc)=>(p.earnings||[]).filter(e=>e.desc===desc).reduce((s,e)=>s+(+e.amount||0),0); const getAllow=(p)=>(p.earnings||[]).filter(e=>e.desc.toLowerCase().includes('allowance')||((e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&(e.remark||'').toUpperCase().includes('ALLOWANCE'))).reduce((s,e)=>s+(+e.amount||0),0); const getInc=(p)=>(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&!e.desc.toLowerCase().includes('allowance')&&!(e.remark||'').toUpperCase().includes('ALLOWANCE')).reduce((s,e)=>s+(+e.amount||0),0); let totBasic=0,totComm=0,totAllow=0,totInc=0,totGross=0,totDed=0,totNet=0; const rows = records.map(p=>{ const basic=get(p,'BASIC PAY'), comm=get(p,'COMMISSION'); const allow=getAllow(p), inc=getInc(p); const gross=p.grossEarnings||0, ded=p.totalDeductions||0, net=p.netPay||0; totBasic+=basic;totComm+=comm;totAllow+=allow;totInc+=inc;totGross+=gross;totDed+=ded;totNet+=net; return` ${p.periodLabel||'โ€”'} ${RM(basic)} ${comm?RM(comm):'โ€”'} ${allow?RM(allow):'โ€”'} ${inc?RM(inc):'โ€”'} ${RM(gross)} ${RM(ded)} ${RM(net)} `; }).join(''); document.getElementById('emp_txn_name').textContent=(emp.name||empNo)+(emp.resigned?' (Resigned)':''); document.getElementById('emp_txn_sub').textContent=`${empNo} ยท ${emp.department||''} ยท ${records.length} payroll record${records.length!==1?'s':''}`; document.getElementById('emp_txn_body').innerHTML=rows||'No records found'; document.getElementById('emp_txn_foot').innerHTML=` TOTAL ${RM(totBasic)} ${totComm?RM(totComm):'โ€”'} ${totAllow?RM(totAllow):'โ€”'} ${totInc?RM(totInc):'โ€”'} ${RM(totGross)} ${RM(totDed)} ${RM(totNet)} `; const ov=document.getElementById('emp_txn_overlay'); ov.style.display='flex'; } function closeEmpTxn(){document.getElementById('emp_txn_overlay').style.display='none';} function initPayrollSummary(){ document.getElementById('psum_table').addEventListener('click',function(e){ const cell=e.target.closest('.ps-name-cell'); if(!cell)return; const empNo=cell.dataset.empno; const period=cell.dataset.period||null; showPSDetail(empNo,period||null); }); // Default to most recent period that has payslips const periods = [...new Set(PS_LIST.map(p=>p.periodLabel))]; const sel = document.getElementById('psum_period'); if(sel && periods.length){ const latest = PP_LIST.filter(p=>periods.includes(p.label)).pop(); if(latest) sel.value = latest.label; } renderPayrollSummary(); } function renderPayrollSummary(){ const period = document.getElementById('psum_period')?.value; const statusFilter = document.getElementById('psum_status')?.value; const empFilter = document.getElementById('psum_emp')?.value||''; const isAll = period === '__ALL__'; const list = isAll ? PS_LIST : PS_LIST.filter(p => p.periodLabel === period); // Filter by active status if needed const rows = list.filter(p => { if(empFilter && p.empNo !== empFilter) return false; if(statusFilter === 'active'){ const emp = HR_EMPS.find(e=>e.empNo===p.empNo); return !emp?.resigned; } return true; }).sort((a,b)=>a.empNo.localeCompare(b.empNo)); const f = v => v ? fmt(v) : 'โ€”'; const RM = v => v ? fmt(v) : '0.00'; // For full year: aggregate per employee across all periods let rowData; if(isAll){ const empMap={}; list.forEach(p=>{ if(empFilter && p.empNo!==empFilter)return; if(!empMap[p.empNo]){ const emp=HR_EMPS.find(e=>e.empNo===p.empNo); if(statusFilter==='active'&&emp?.resigned)return; empMap[p.empNo]={empNo:p.empNo,empName:p.empName,department:p.department, basic:0,comm:0,allow:0,incentive:0,grossEarnings:0,unpaid:0, epf:0,socso:0,eis:0,tax:0,totalDeductions:0,netPay:0, emp_epf:0,emp_socso:0,emp_eis:0, resigned:emp?.resigned,periods:0}; } const agg=empMap[p.empNo]; agg.basic+=((p.earnings||[]).find(e=>e.desc==='BASIC PAY')?.amount||0); agg.comm+=(p.earnings||[]).filter(e=>e.desc==='COMMISSION').reduce((s,e)=>s+(+e.amount||0),0); agg.allow+=(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('allowance')||((e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&(e.remark||'').toUpperCase().includes('ALLOWANCE')))).reduce((s,e)=>s+(+e.amount||0),0); agg.incentive+=(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&!e.desc.toLowerCase().includes('allowance')&&!(e.remark||'').toUpperCase().includes('ALLOWANCE')).reduce((s,e)=>s+(+e.amount||0),0); agg.grossEarnings+=(p.grossEarnings||0); agg.unpaid+=(p.ded?.unpaid||0); agg.epf+=(p.ded?.epf||0);agg.socso+=(p.ded?.socso||0);agg.eis+=(p.ded?.eis||0);agg.tax+=(p.ded?.tax||0); agg.totalDeductions+=(p.totalDeductions||0);agg.netPay+=(p.netPay||0); agg.emp_epf+=(p.emp?.epf||0);agg.emp_socso+=(p.emp?.socso||0);agg.emp_eis+=(p.emp?.eis||0); agg.periods++; }); rowData=Object.values(empMap).sort((a,b)=>a.empNo.localeCompare(b.empNo)).map(agg=>({p:agg,comm:agg.comm,allow:agg.allow,incentive:agg.incentive,resigned:agg.resigned,isAgg:true})); } else { rowData = rows.map(p => { const comm = (p.earnings||[]).filter(e=>e.desc==='COMMISSION').reduce((s,e)=>s+(+e.amount||0),0); const allow = (p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('allowance')||((e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&(e.remark||'').toUpperCase().includes('ALLOWANCE')))).reduce((s,e)=>s+(+e.amount||0),0); const incentive = (p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&!e.desc.toLowerCase().includes('allowance')&&!(e.remark||'').toUpperCase().includes('ALLOWANCE')).reduce((s,e)=>s+(+e.amount||0),0); const emp = HR_EMPS.find(e=>e.empNo===p.empNo); const resigned = emp?.resigned; return {p, comm, allow, incentive, resigned}; }); } // Totals const tot = (key) => rowData.reduce((s,{p})=>s+(+p[key]||0),0); const totComm = rowData.reduce((s,{comm})=>s+comm,0); const totAllow = rowData.reduce((s,{allow})=>s+allow,0); const totIncentive = rowData.reduce((s,{incentive})=>s+(incentive||0),0); const totEmpEpf = rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.emp_epf||0):(+p.emp?.epf||0)),0); const totEmpSoc = rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.emp_socso||0):(+p.emp?.socso||0)),0); const totEmpEis = rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.emp_eis||0):(+p.emp?.eis||0)),0); document.getElementById('psum_meta').textContent = `${rows.length} employees โ€ข Period: ${isAll?'Full Year 2026':period||'โ€”'}`; // KPI const kpiEl = document.getElementById('psum_kpi'); if(kpiEl) kpiEl.innerHTML = [ kpi('blue','Employees',rows.length+''), kpi('teal','Total Basic','RM '+fmt(tot('grossEarnings')-totComm-totAllow-totIncentive)), kpi('yellow','Comm + Allow + Incentive','RM '+fmt(totComm+totAllow+totIncentive)), kpi('red','Total Deductions','RM '+fmt(tot('totalDeductions'))), kpi('green','Total Net Pay','RM '+fmt(tot('netPay'))) ].join(''); const tbody = document.getElementById('psum_body'); if(tbody) tbody.innerHTML = rowData.map(({p,comm,allow,incentive,resigned,isAgg},i)=>{ const basic=isAgg?p.basic:((p.earnings||[]).find(e=>e.desc==='BASIC PAY')?.amount||0); const gross=isAgg?p.grossEarnings:(p.grossEarnings||0); const unpaid=isAgg?p.unpaid:(p.ded?.unpaid||0); const epf_e=isAgg?p.epf:(p.ded?.epf||0); const soc_e=isAgg?p.socso:(p.ded?.socso||0); const eis_e=isAgg?p.eis:(p.ded?.eis||0); const tax=isAgg?p.tax:(p.ded?.tax||0); const totded=isAgg?p.totalDeductions:(p.totalDeductions||0); const net=isAgg?p.netPay:(p.netPay||0); const ep_epf=isAgg?p.emp_epf:(p.emp?.epf||0); const ep_soc=isAgg?p.emp_socso:(p.emp?.socso||0); const ep_eis=isAgg?p.emp_eis:(p.emp?.eis||0); const dept=isAgg?p.department:(p.department||''); return` ${i+1} ${p.empNo} ${p.empName}
${dept}${isAgg&&p.periods>1?` (${p.periods} months)`:''}
${RM(basic)} ${comm?RM(comm):'โ€”'} ${allow?RM(allow):'โ€”'} ${incentive?RM(incentive):'โ€”'} ${RM(gross)} ${unpaid?RM(unpaid):'โ€”'} ${RM(epf_e)} ${RM(soc_e)} ${RM(eis_e)} ${RM(tax)} ${RM(totded)} ${RM(net)} ${RM(ep_epf)} ${RM(ep_soc)} ${RM(ep_eis)} ${resigned?'Resigned':'Active'} `;}).join(''); const tfoot = document.getElementById('psum_foot'); if(tfoot) tfoot.innerHTML = ` TOTAL (${rowData.length} staff${isAll?' ยท Full Year 2026':''}) ${RM(rowData.reduce((s,{p,isAgg})=>s+(isAgg?p.basic:((p.earnings||[]).find(e=>e.desc==='BASIC PAY')?.amount||0)),0))} ${RM(totComm)} ${RM(totAllow)} ${RM(totIncentive)} ${RM(tot('grossEarnings'))} ${RM(rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.unpaid||0):(+p.ded?.unpaid||0)),0))} ${RM(rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.epf||0):(+p.ded?.epf||0)),0))} ${RM(rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.socso||0):(+p.ded?.socso||0)),0))} ${RM(rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.eis||0):(+p.ded?.eis||0)),0))} ${RM(rowData.reduce((s,{p,isAgg})=>s+(isAgg?(p.tax||0):(+p.ded?.tax||0)),0))} ${RM(tot('totalDeductions'))} ${RM(tot('netPay'))} ${RM(totEmpEpf)} ${RM(totEmpSoc)} ${RM(totEmpEis)} `; } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ ACCOUNT SUMMARY PAGE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• const ACCT_MONTHS=['2026-01','2026-02','2026-03','2026-04','2026-05','2026-06','2026-07','2026-08','2026-09','2026-10','2026-11','2026-12']; const ACCT_ML={'2026-01':'Jan','2026-02':'Feb','2026-03':'Mar','2026-04':'Apr','2026-05':'May','2026-06':'Jun','2026-07':'Jul','2026-08':'Aug','2026-09':'Sep','2026-10':'Oct','2026-11':'Nov','2026-12':'Dec'}; const ACCT_STRUCTURE=[ {section:'Income',key:'income',color:'#16a34a',items:[ {label:'Design Fee Income',match:(r)=>/design.?fee|design.?income/i.test(r.billInfo||'')}, {label:'Construction Income',match:(r)=>/construction.?income|construction.?fee/i.test(r.billInfo||'')}, {label:'Others (Referal Commission/Redemption)',match:(r)=>/referal|referral|commission.?income|redemption/i.test(r.billInfo||'')}, {label:'Project VO',match:(r)=>/project.?vo|variation.?order/i.test(r.billInfo||'')}, {label:'Government Grant',match:(r)=>/grant|government/i.test(r.billInfo||'')}, {label:'Refund',match:(r)=>/refund/i.test(r.billInfo||'')}, {label:'Others',match:(r)=>true} ]}, {section:'Office Expenses',key:'office',color:'#dc2626',items:[ {label:'Accounting Fee'},{label:'Advertisement'},{label:'Administrator Fee'}, {label:'BSN Loan'},{label:'Car Loan'},{label:'Copier Machine Rental Fee'}, {label:'CP 204 (Tax)'},{label:'Depreciation'},{label:'Entertainment'}, {label:'Google Cloud Subcription Fee'},{label:'Gift'},{label:'Groceries'}, {label:'Hardware & Consumables'},{label:'License Fee'},{label:'Levy'}, {label:'Medical Fee'},{label:'Membership Fee'},{label:'NW (grant application fee)'}, {label:'Office Cleaning Fee'},{label:'Office Rental Fee'}, {label:'Printing and Stationery'},{label:'Petrol/Toll/Parking Expenses'}, {label:'Penalty Charges'},{label:'Rebrand Graphic'},{label:'Runner Fee'}, {label:'Stamping Fees'},{label:'Telephone & Internet (Unifi)'}, {label:'Telephone & Internet (Maxis)'},{label:'Transportation Charges'}, {label:'Tax Agent Fee'},{label:'Uniform'},{label:'Upkeep of Office'}, {label:'Upkeep of Computer & Software'},{label:'Water Dispenser Rental Fee'}, {label:'Water and Electricity (TNB)'},{label:'Water and Electricity (SAJ)'}, {label:'Marketing Expense (Xiaohongshu)'}, {label:'Marketing Expenses (Capcut Membership)'}, {label:'Marketing Expenses (Canva Subscribtion)'},{label:'E-Stamping Fees'}, {label:'Others (Office)'} ]}, {section:'Salary Expenses',key:'salary',color:'#d97706',items:[ {label:'Employee Salary & Commission',src:'ps_salary'}, {label:'Employee EPF',src:'ps_epf'}, {label:'Employee PERKESO (SOCSO & EIS)',src:'ps_perkeso'}, {label:'Employee Incentive',src:'ps_incentive'}, {label:'Partner Salary'},{label:'Partner EPF'},{label:'Partner PERKESO (SOCSO & EIS)'}, {label:'Partner Incentive'},{label:'Director Withdraw'},{label:'Company Trip'} ]}, {section:'Project Expenses',key:'project',color:'#7c3aed',items:[ {label:'Photoshooting Fee'}, {label:'Acts ID Hardware Sdn Bhd'},{label:'Ak Engineering & ACMV Sdn Bhd'}, {label:'Alumaestro Sdn Bhd'},{label:'Aspire Floors Sdn Bhd'}, {label:'AT Wood Furniture'},{label:'Badan Pungurusan Bersama Ekoflora 2'}, {label:'BB Solution Enterpricse'},{label:'Best Light City Sdn Bhd'}, {label:'Betterment Dot Com Sdn Bhd'},{label:'BH 93 Enterprise'}, {label:'Chuan Siang Renovation (M) Sdn Bhd'}, {label:'Chuan Yoong Mosaic & Construction Works'}, {label:'Chee Hui Stainless Steel'},{label:'Chwee Hwa Nursery Sdn Bhd'}, {label:'Chong Yong Peng'},{label:'Classino Stone Trading'}, {label:'Conteng Studio'},{label:'CS Steel & Iron Engineering'}, {label:'DDS Aludna Sdn Bhd'},{label:'Denson Smart Technology Sdn. Bhd'}, {label:'Double Man Design'},{label:'Eco Light Electrical'}, {label:'Ecoware International (M) Sdn Bhd'},{label:'Elitaco Sdn Bhd'}, {label:'Enzeh Pest Resources Sdn Bhd'}, {label:'Feruni Ceramiche Sdn Bhd - FRS Tebrau'}, {label:'Five Star Cleaning Enterprise'}, {label:'First Magicseal Express Enterprise'}, {label:'Flooring Master Enterprise'},{label:'Gitaly Sdn Bhd'}, {label:'Goh Koon Tee'},{label:'Goodrich Global Sdn Bhd'}, {label:'Haner Ean Protect Sdn Bhd'},{label:'Hongye Renovation & Construction Sdn. Bhd.'}, {label:'Home Crative Lab Sdn Bhd'},{label:'Homeworks (Southern) Sdn Bhd'}, {label:'HQ Stainless Steel Sdn Bhd'},{label:'Ideals Woods Project Sdn Bhd'}, {label:'Jason Tham Man Hou (Funky Entertainment & Services)'}, {label:'Jm Conceptual Decor'},{label:'Jubin BMS(1990) Sdn Bhd'}, {label:'Kmc Construction Work'},{label:'Kim Yap Engineering Sdn. Bhd.'}, {label:'Kimway Stone Industry Sdn Bhd'},{label:'KK Hoo Aircond Services'}, {label:'Klot Resources (M) Sdn Bhd'},{label:'Kronotex Trading'}, {label:'Lim HF Construction'},{label:'Lam Hoi Seong'}, {label:'Lc Wei Electrician and Renovation'},{label:'Mastile Tilling Sdn Bhd'}, {label:'Macroline Solution Enterprise'},{label:'Mega Tiles (M) Sdn Bhd'}, {label:'Meng Jiang Trading'},{label:'Ming Shen Cleaning Services'}, {label:'Mitalee Carpet & Furnishing Sdn bhd'},{label:'Nenek Forest Sdn Bhd'}, {label:'Noon Plaster Ceiling & Renovation'},{label:'Pavillion Lighting Sdn Bhd'}, {label:'Poh Zi Yang'},{label:'PRO Cleaning Enterprise'}, {label:'Quantity Village Sdn. Bhd.'},{label:'Reenex Curtain & Wallpaper Sdn Bhd'}, {label:'Rooftop Waterproofing Hub'},{label:'Seng Ho Electrical Service'}, {label:'Sheng Chew Fitment Enterprise'},{label:'Shien Feng Renovation Enterprise'}, {label:'Shuda Logistic Sdn Bhd'},{label:'Silver Recycle Enterprise'}, {label:'Sin Yu Lee Creative (M)'},{label:'Sin Soon Hup Furniture Sdn Bhd'}, {label:'Small Object Store'},{label:'StoneTop Renovation'}, {label:'Superior Office Solutions'},{label:'Tavillion Sdn Bhd'}, {label:'TGS Furnishings Sdn Bhd'},{label:'Ticlean Cleaning Service Enterprise'}, {label:'Tocos Living (M) Sdn Bhd'},{label:'Top Idea Sdn Bhd'}, {label:'Tm Sanitary Sdn Bhd'},{label:'VIP Lighting and Service'}, {label:'Walden Lighting Solution'},{label:'WH Wood Specialist Interior'}, {label:'Wong Twee Hian'},{label:'Wong Zhi Yuh'}, {label:'Wong Cleaning Service'},{label:'Xin Yao Interior Design'}, {label:'Yi Rong Renovatlon Works'},{label:'Yong Cheu Chai (Yau Plumbing)'}, {label:'Yong & Lee Plumbing & Engineering'},{label:'ZYDI Design Sdn Bhd'}, {label:'Contractor Treat'},{label:'Staff Claim - Project Expenses'}, {label:'Credit Card Claim - Project Expenses'},{label:'Others (Project)'} ]} ]; function getAcctVal(month){ const mo=month; // '2026-01' const txns=DATA.filter(r=>r.date&&r.date.startsWith(mo)); const received=txns.filter(r=>r.type==='Payment Received'); const created=txns.filter(r=>r.type==='Payment Create'); // Build lookup maps const officeMap={}; created.filter(r=>getR(r).cat==='Office Expenses').forEach(r=>{ const mr=getR(r);const k=(mr.billInfo||'Others (Office)'); officeMap[k]=(officeMap[k]||0)+(mr.submittedAmt||0); }); const projectMap={}; created.filter(r=>getR(r).cat==='Project Expenses').forEach(r=>{ const mr=getR(r);const k=(mr.payee||mr.billInfo||'Others (Project)'); projectMap[k]=(projectMap[k]||0)+(mr.submittedAmt||0); }); // Salary from PS_LIST for this month const pp=PP_LIST.find(p=>p.start&&p.start.startsWith(mo)); const psForMonth=pp?PS_LIST.filter(p=>p.periodLabel===pp.label):[]; const ps_salary=psForMonth.reduce((s,p)=>s+(p.grossEarnings||0),0); const ps_epf=psForMonth.reduce((s,p)=>s+(p.emp?.epf||0),0); const ps_perkeso=psForMonth.reduce((s,p)=>s+((p.emp?.socso||0)+(p.emp?.eis||0)),0); const ps_incentive=psForMonth.reduce((s,p)=>s+(p.earnings||[]).filter(e=>e.desc==='INCENTIVE / BONUS').reduce((a,e)=>a+(+e.amount||0),0),0); return {received,officeMap,projectMap,ps_salary,ps_epf,ps_perkeso,ps_incentive}; } function resolveAcctItem(item,sec,mv,billInfo_income_used){ if(sec.key==='income'){ if(item.label==='Others'){ // sum all received not yet used return mv.received.filter(r=>!billInfo_income_used.has(r.no)).reduce((s,r)=>s+(r.amtReceived||0),0); } const matched=mv.received.filter(r=>item.match(r)); matched.forEach(r=>billInfo_income_used.add(r.no)); return matched.reduce((s,r)=>s+(r.amtReceived||0),0); } if(sec.key==='office'){ if(item.label==='Others (Office)'){ // sum all office txns not matched to known items const knownLabels=sec.items.filter(i=>i.label!=='Others (Office)').map(i=>i.label.toLowerCase()); let s=0; for(const [k,v] of Object.entries(mv.officeMap)){ if(!knownLabels.some(kl=>k.toLowerCase().includes(kl)||kl.includes(k.toLowerCase()))){s+=v;} } return s; } // fuzzy match let s=0; for(const [k,v] of Object.entries(mv.officeMap)){ const kl=k.toLowerCase(),il=item.label.toLowerCase(); if(kl===il||kl.includes(il)||il.includes(kl)){s+=v;} } return s; } if(sec.key==='salary'){ if(item.src==='ps_salary')return mv.ps_salary; if(item.src==='ps_epf')return mv.ps_epf; if(item.src==='ps_perkeso')return mv.ps_perkeso; if(item.src==='ps_incentive')return mv.ps_incentive; // Non-PS salary items from transactions const catTxns=DATA.filter(r=>r.date&&r.date.startsWith(mv.month)&&r.type==='Payment Create'&&(getR(r).cat==='Salary Expenses')); const il=item.label.toLowerCase(); return catTxns.filter(r=>{const mr=getR(r);return(mr.billInfo||'').toLowerCase().includes(il)||(mr.payee||'').toLowerCase().includes(il);}).reduce((s,r)=>s+(getR(r).submittedAmt||0),0); } if(sec.key==='project'){ if(item.label==='Others (Project)'){ const knownLabels=sec.items.filter(i=>i.label!=='Others (Project)').map(i=>i.label.toLowerCase()); let s=0; for(const [k,v] of Object.entries(mv.projectMap)){ if(!knownLabels.some(kl=>k.toLowerCase().includes(kl)||kl.includes(k.toLowerCase()))){s+=v;} } return s; } let s=0; const il=item.label.toLowerCase(); for(const [k,v] of Object.entries(mv.projectMap)){ if(k.toLowerCase().includes(il)||il.includes(k.toLowerCase())){s+=v;} } return s; } return 0; } let _acctData=null; let _acctCollapsed={income:false,office:false,salary:false,project:false}; function buildAcctData(){ const data={}; ACCT_MONTHS.forEach(mo=>{ const mv=getAcctVal(mo); mv.month=mo; data[mo]={}; ACCT_STRUCTURE.forEach(sec=>{ const used=new Set(); sec.items.forEach(item=>{ data[mo][sec.key+'_'+item.label]=resolveAcctItem(item,sec,mv,used); }); }); }); _acctData=data; } function acctSectionTotal(sec,month){ if(!_acctData||!_acctData[month])return 0; return sec.items.reduce((s,item)=>s+(_acctData[month][sec.key+'_'+item.label]||0),0); } function acctItemTotal(sec,item){ if(!_acctData)return 0; return ACCT_MONTHS.reduce((s,mo)=>s+(_acctData[mo][sec.key+'_'+item.label]||0),0); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ ACCOUNT SYSTEM โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ Main Page โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function renderAccSummary(){ const el=document.getElementById('content'); if(el)el.innerHTML=accountSummaryPage(); } function setAccSumYear(y){_accSumYear=y;renderAccSummary();} function accountSummaryPage(){ // โ”€โ”€ Year filter โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const _allYears=[...new Set(ACC_TXNS.map(t=>{const d=t.receivedDate||t.submittedDate||'';return d.slice(0,4);}).filter(Boolean))].sort((a,b)=>b-a); const _yr=_accSumYear; const _txnFilter=t=>{if(!_yr)return true;const d=t.receivedDate||t.submittedDate||'';return d.startsWith(_yr);}; const _psFilter=p=>{if(!_yr)return true;return(p.periodLabel||'').includes(_yr);}; const inTxns = ACC_TXNS.filter(t=>t.type==='in'&&_txnFilter(t)); const outTxns = ACC_TXNS.filter(t=>t.type==='out'&&_txnFilter(t)); // โ”€โ”€ INCOME sub-category mapping โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // Haystack: category + payeeName + workDescription + remarks + billNo function _incomeHay(t){ return [t.category||'',...(t.subCategories||[]),t.payeeName||'',t.workDescription||'',t.remarks||'',t.billNo||''].join(' '); } // Order matters โ€” first match wins const INCOME_CATS=[ {label:'Design Fee Income', rx:/design.?income|design.?fee|\bdesign\b/i}, {label:'Construction Income', rx:/construction.?income|\bconstruction\b|project.?income/i}, {label:'Government Training Incentive', rx:/government.?grant|government.?training|training.?incentive|\btip\b/i}, {label:'Redemption', rx:/redeem|redemption/i}, {label:'Payment Refund', rx:/refund/i}, {label:'Referral Commission', rx:/referral|commission/i}, {label:'Others', rx:/.+/}, // catch-all ]; const incomeByCat={}; INCOME_CATS.forEach(c=>incomeByCat[c.label]=[]); inTxns.forEach(t=>{ const hay=_incomeHay(t); for(const {label,rx} of INCOME_CATS){if(rx.test(hay)){incomeByCat[label].push(t);break;}} }); // โ”€โ”€ SALARY from Payroll Summary data (PS_LIST) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const _partnerNos=new Set(HR_EMPS.filter(e=>e.position==='Director').map(e=>e.empNo)); const _salAgg={ 'Employee Salary & Commission':{amt:0,cnt:0}, 'Employee EPF (KWSP)':{amt:0,cnt:0}, 'Employee PERKESO (SOCSO & EIS)':{amt:0,cnt:0}, 'Employee Incentive':{amt:0,cnt:0}, 'Partner Salary':{amt:0,cnt:0}, 'Partner EPF (KWSP)':{amt:0,cnt:0}, 'Partner PERKESO (SOCSO & EIS)':{amt:0,cnt:0}, 'Partner Incentive':{amt:0,cnt:0}, }; PS_LIST.filter(_psFilter).forEach(p=>{ const isP=_partnerNos.has(p.empNo); const gross=p.grossEarnings||0; const incentive=(p.earnings||[]).filter(e=>(e.desc.toLowerCase().includes('incentive')||e.desc.toLowerCase().includes('bonus'))&&!e.desc.toLowerCase().includes('allowance')&&!(e.remark||'').toUpperCase().includes('ALLOWANCE')).reduce((s,e)=>s+(+e.amount||0),0); const epfTotal=(p.ded?.epf||0)+(p.emp?.epf||0); const perkTotal=(p.ded?.socso||0)+(p.ded?.eis||0)+(p.emp?.socso||0)+(p.emp?.eis||0); const pfx=isP?'Partner':'Employee'; const salKey=isP?'Partner Salary':'Employee Salary & Commission'; _salAgg[salKey].amt+=(gross-incentive);_salAgg[salKey].cnt++; if(incentive>0){_salAgg[pfx+' Incentive'].amt+=incentive;_salAgg[pfx+' Incentive'].cnt++;} if(epfTotal>0){_salAgg[pfx+' EPF (KWSP)'].amt+=epfTotal;_salAgg[pfx+' EPF (KWSP)'].cnt++;} if(perkTotal>0){_salAgg[pfx+' PERKESO (SOCSO & EIS)'].amt+=perkTotal;_salAgg[pfx+' PERKESO (SOCSO & EIS)'].cnt++;} }); const salTxns=outTxns.filter(t=>t.category==='Salary Expense'); // โ”€โ”€ OTHER SECTIONS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const officeTxns =outTxns.filter(t=>t.category==='Office Expense'); const projectTxns =outTxns.filter(t=>t.category==='Project Expense'); const dirClaimTxns =outTxns.filter(t=>t.category==='Director Withdraw'); // โ”€โ”€ OFFICE EXPENSE โ€” sub-category breakdown โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // Matches against subCategories[], payeeName, workDescription, remarks (in that priority) const OFFICE_CATS=[ {label:'Accounting Fee', rx:/accounting.?fee/i}, {label:'Advertisement', rx:/advert/i}, {label:'BSN Loan', rx:/bsn.?loan/i}, {label:'Car Loan', rx:/car.?loan/i}, {label:'Copier Machine', rx:/copier/i}, {label:'Income Tax (CP204)', rx:/income.?tax|cp.?204|\bpcb\b/i}, {label:'Entertainment', rx:/entertainment/i}, {label:'Google Workspace', rx:/google.?workspace/i}, {label:'Gift', rx:/\bgift\b/i}, {label:'Groceries', rx:/grocer/i}, {label:'License Fee', rx:/licen[sc]e/i}, {label:'Levy', rx:/\blevy\b/i}, {label:'Medical Fee', rx:/medical/i}, {label:'Office Cleaning', rx:/office.?clean|clean.*office|\bcleaning\b/i}, {label:'Services', rx:/\bservice[s]?\b/i}, {label:'Office Rental Fee', rx:/office.?rental|rental.?fee/i}, {label:'Grant Application Fee', rx:/grant.?appli|grant.?submiss/i}, {label:'SSM Renewal', rx:/\bssm\b/i}, {label:'Printing and Stationery', rx:/printing|stationery/i}, {label:'Membership Fee', rx:/membership/i}, {label:'Site Use', rx:/site.?use/i}, {label:'Penalty Charges', rx:/penalty/i}, {label:'Rebrand Graphic', rx:/rebrand|graphic/i}, {label:'Runner Fee', rx:/runner/i}, {label:'Telephone & Internet (Unifi)',rx:/unifi/i}, {label:'Telephone & Internet (Maxis)',rx:/maxis/i}, {label:'Transportation Charges', rx:/transport/i}, {label:'Tax Agent Fee', rx:/tax.?agent/i}, {label:'Uniform', rx:/\buniform\b/i}, {label:'Upkeep of Office', rx:/upkeep.?of.?office/i}, {label:'Upkeep of Computer & Software',rx:/upkeep.?(of.?)?computer|software|office.?monitor/i}, {label:'Office Upkeep', rx:/office.?upkeep|\bupkeep\b/i}, {label:'Water Dispenser Rental Fee', rx:/water.?dispenser/i}, {label:'Water and Electricity (TNB)', rx:/\btnb\b|tenaga/i}, {label:'Water and Electricity (SAJ)', rx:/\bsaj\b/i}, {label:'Marketing Expenses', rx:/marketing/i}, {label:'E-Stamping Fees', rx:/e.?stamp|stamp.*fee/i}, ]; // Include billNo in matching so e.g. billNo:'SSM Renewal' gets caught function _officeHay(t){ return [...(t.subCategories||[]),t.payeeName||'',t.workDescription||'',t.remarks||'',t.billNo||''].join(' '); } const officeByLabel={}; OFFICE_CATS.forEach(c=>officeByLabel[c.label]=[]); const officeUnmatched=[]; officeTxns.forEach(t=>{ const hay=_officeHay(t); let found=false; for(const {label,rx} of OFFICE_CATS){if(rx.test(hay)){officeByLabel[label].push(t);found=true;break;}} if(!found)officeUnmatched.push(t); }); // โ”€โ”€ INCOME โ€” breakdown by Project Code โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const incomeByProj={}; inTxns.forEach(t=>{ const codes=[...(t.projectCode?[t.projectCode]:[]),...(t.projectSplits||[]).map(s=>s.code).filter(Boolean)]; const uniq=[...new Set(codes)]; if(uniq.length){uniq.forEach(c=>{if(!incomeByProj[c])incomeByProj[c]=[];incomeByProj[c].push(t);});} else{if(!incomeByProj['(No Project)'])incomeByProj['(No Project)']=[];incomeByProj['(No Project)'].push(t);} }); // โ”€โ”€ PROJECT EXPENSE โ€” breakdown by Project Code โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const projectByCode={}; projectTxns.forEach(t=>{ const code=(t.projectCode||(t.projectSplits||[])[0]?.code)||'(No Project Code)'; if(!projectByCode[code])projectByCode[code]=[]; projectByCode[code].push(t); }); // โ”€โ”€ TOTALS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ const totalIncome =inTxns.reduce((s,t)=>s+(t.amountReceived||0),0); const totalSalary =Object.values(_salAgg).reduce((s,v)=>s+v.amt,0); const totalOffice =officeTxns.reduce((s,t)=>s+(t.submittedAmount||0),0); const totalProject =projectTxns.reduce((s,t)=>s+(t.submittedAmount||0),0); const totalDirClaim =dirClaimTxns.reduce((s,t)=>s+(t.submittedAmount||0),0); const totalExpenses =totalSalary+totalOffice+totalProject+totalDirClaim; const net=totalIncome-totalExpenses; // Exclude recurring from expense/net totals const totalOfficeNR =officeTxns.filter(t=>!t.isRecurring).reduce((s,t)=>s+(t.submittedAmount||0),0); const totalProjectNR =projectTxns.filter(t=>!t.isRecurring).reduce((s,t)=>s+(t.submittedAmount||0),0); const totalDirClaimNR =dirClaimTxns.filter(t=>!t.isRecurring).reduce((s,t)=>s+(t.submittedAmount||0),0); const totalExpensesNR =totalSalary+totalOfficeNR+totalProjectNR+totalDirClaimNR; const netNR=totalIncome-totalExpensesNR; const totalRecurringExpAmt=outTxns.filter(t=>t.isRecurring).reduce((s,t)=>s+(t.submittedAmount||0),0); // Exclude recurring from pending โ€” recurring auto-approves; only manual payments matter function pending(arr){return arr.filter(t=>!t.approvedDate&&!t.isRecurring).reduce((s,t)=>s+(t.submittedAmount||0),0);} function pendingCount(arr){return arr.filter(t=>!t.approvedDate&&!t.isRecurring).length;} const pendingRecurringAmt=outTxns.filter(t=>!t.approvedDate&&t.isRecurring).reduce((s,t)=>s+(t.submittedAmount||0),0); const pendingProj =pending(projectTxns); const pendingOffice =pending(officeTxns); const pendingOther =pending(outTxns.filter(t=>t.category!=='Project Expense'&&t.category!=='Office Expense')); const totalPending =pendingProj+pendingOffice+pendingOther+pendingRecurringAmt; const totalPendingCount=pendingCount(outTxns); // โ”€โ”€ RENDER HELPERS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // Helper: comma-separated IDs for inline onclick function _ids(txns){return txns.map(t=>t.id).join(',');} function subRow(label,txns,isIn,filterCat){ const amt=txns.reduce((s,t)=>s+(isIn?t.amountReceived||0:t.submittedAmount||0),0); const has=txns.length>0; const idStr=_ids(txns); const typeArg=isIn?'true':'false'; const labelEsc=label.replace(/'/g,"\\'"); return` ${label} ${amt>0?RM(amt):'โ€”'} ${txns.length||'โ€”'} ${has?`View โ†’`:''} `; } function officeSubRow(label,txns){ const amt=txns.reduce((s,t)=>s+(t.submittedAmount||0),0); const has=txns.length>0; const idStr=_ids(txns); const labelEsc=label.replace(/'/g,"\\'"); const navEsc=label.replace(/'/g,"\\'"); return` ${label} ${amt>0?RM(amt):'โ€”'} ${txns.length||'โ€”'} ${has?`View โ†’`:''} `; } function projCodeRow(code,txns){ const amt=txns.reduce((s,t)=>s+(t.submittedAmount||0),0); const idStr=_ids(txns); const codeEsc=code.replace(/'/g,"\\'"); return` ${code} ${RM(amt)} ${txns.length} View โ†’ `; } function incomeProjRow(code,txns){ const amt=txns.reduce((s,t)=>s+(t.amountReceived||0),0); const idStr=_ids(txns); const codeEsc=code.replace(/'/g,"\\'"); const isNoProj=code==='(No Project)'; return` ${code} ${RM(amt)} ${txns.length} View โ†’ `; } function salSubRow(label,data){ const {amt,cnt}=data; return` ${label} ${amt>0?RM(amt):'โ€”'} ${cnt||'โ€”'} `; } function groupHeader(label){ return`${label}`; } function sectionCard(icon,label,total,color,subRows,pendingAmt=0,filterCat='',filterType=''){ return`
${icon} ${label}
${RM(total)}
${pendingAmt>0?`
โณ ${RM(pendingAmt)} pending approval
`:''}
โ€บ
${subRows?`${subRows}
Sub-CategoryAmountRecords
`:'
No transactions yet
'}
`; } // Income: category breakdown only (click to drill down into modal) const incomeSubRows=INCOME_CATS.map(({label})=>subRow(label,incomeByCat[label]||[],true,'Design Income')).join(''); const salarySubRows= groupHeader('Employee')+ ['Employee Salary & Commission','Employee EPF (KWSP)','Employee PERKESO (SOCSO & EIS)','Employee Incentive'].map(s=>salSubRow(s,_salAgg[s]||{amt:0,cnt:0})).join('')+ groupHeader('Partner')+ ['Partner Salary','Partner EPF (KWSP)','Partner PERKESO (SOCSO & EIS)','Partner Incentive'].map(s=>salSubRow(s,_salAgg[s]||{amt:0,cnt:0})).join(''); // Store unmatched IDs globally so navToAccUnmatched() can use them _summaryUnmatchedIds=officeUnmatched.map(t=>t.id); // Office sub-rows โ€” all 33 categories, always shown (greyed if empty), plus Unmatched const _unmatchedAmt=officeUnmatched.reduce((s,t)=>s+(t.submittedAmount||0),0); const officeSubRows= OFFICE_CATS.map(({label})=>officeSubRow(label,officeByLabel[label]||[])).join('')+ (officeUnmatched.length?(()=>{ const idStr=_ids(officeUnmatched); return` โš  Unmatched / Other ${RM(_unmatchedAmt)} ${officeUnmatched.length} View โ†’ `; })():''); // Project sub-rows โ€” sorted by code const projSubRows=Object.entries(projectByCode) .sort(([a],[b])=>a.localeCompare(b)) .map(([code,txns])=>projCodeRow(code,txns)) .join(''); return`
${_yr?`๐Ÿ“… ${_yr}`:''}
Total Income
${RM(totalIncome)}
${INCOME_CATS.filter(({label})=>(incomeByCat[label]||[]).length>0).map(({label})=>{ const txns=incomeByCat[label]||[]; const amt=txns.reduce((s,t)=>s+(t.amountReceived||0),0); const emoji=label.includes('Design')?'๐ŸŽจ':label.includes('Construction')?'๐Ÿ—':label.includes('Government')||label.includes('Training')?'๐Ÿ›':label.includes('Redemption')?'๐Ÿ”–':label.includes('Refund')?'โ†ฉ๏ธ':label.includes('Referral')||label.includes('Commission')?'๐Ÿค':'๐Ÿ“'; return`
${emoji} ${label} ${RM(amt)}
`; }).join('')}
Total Expenses
${RM(totalExpenses)}
๐Ÿ— Project Expenses ${totalProject>0?RM(totalProject):'โ€”'}
๐Ÿข Office Expenses ${totalOffice>0?RM(totalOffice):'โ€”'}
${totalSalary>0?`
๐Ÿ‘ค Salary ${RM(totalSalary)}
`:''} ${totalDirClaim>0?`
๐Ÿ“ Director Withdraw ${RM(totalDirClaim)}
`:''}
Net Balance
${RM(net)}
${net>=0?'Surplus':'Deficit'}
Pending Approval
${RM(totalPending)}
๐Ÿ— Project Expenses ${pendingProj>0?RM(pendingProj):'โ€”'}
๐Ÿข Office Expenses ${pendingOffice>0?RM(pendingOffice):'โ€”'}
${pendingOther>0?`
๐Ÿ“ Others ${RM(pendingOther)}
`:''} ${pendingRecurringAmt>0?`
๐Ÿ”„ Recurring (pending) ${RM(pendingRecurringAmt)}
`:''}
${sectionCard('๐Ÿ’ฐ','Income',totalIncome,'var(--green)',incomeSubRows,0,'','in')} ${sectionCard('๐Ÿข','Office Expenses',totalOffice,'var(--red)',officeSubRows,pending(officeTxns),'Office Expense','out')} ${sectionCard('๐Ÿ‘ค','Salary Expenses',totalSalary,'var(--red)',salarySubRows,pending(salTxns),'Salary Expense','out')} ${sectionCard('๐Ÿ“','Project Expenses',totalProject,'var(--red)',projSubRows?projSubRows:null,pending(projectTxns),'Project Expense','out')} ${sectionCard('๐Ÿ“','Director Withdraw',totalDirClaim,'var(--red)',null,pending(dirClaimTxns),'Director Withdraw','out')} `; } function accountSystemPage(){ const total_in=ACC_TXNS.filter(t=>t.type==='in').reduce((s,t)=>s+(t.amountReceived||0),0); const total_out=ACC_TXNS.filter(t=>t.type==='out').reduce((s,t)=>s+(t.submittedAmount||0),0); const net=total_in-total_out; const pending=ACC_TXNS.filter(t=>t.type==='out'&&!t.approvedDate).length; return`
${kpi('green','Total Income',RM(total_in),ACC_TXNS.filter(t=>t.type==='in').length+' records')} ${kpi('red','Total Expenses',RM(total_out),ACC_TXNS.filter(t=>t.type==='out').length+' records')} ${kpi(net>=0?'green':'red','Net',RM(net),net>=0?'Surplus':'Deficit')} ${kpi('yellow','Pending Approval',''+pending,'payments awaiting')}
โ€”
${['Date','Type','Category','Payee / Party','Bank','Bill / Quot No','Amount','Approval'].map((h,i)=>{ const key=['date','type','category','payee','bank','bill','amount','approval'][i]; const isNum=key==='amount'; const active=_accSort.key===key; const arrow=active?(_accSort.asc?' โ–ฒ':' โ–ผ'):''; return``; }).join('')}
ID${_accSort.key==='id'?(_accSort.asc?' โ–ฒ':' โ–ผ'):''}${h}${arrow}File
`; } function accSortBy(key){ if(_accSort.key===key){_accSort.asc=!_accSort.asc;} else{_accSort={key,asc:key!=='date'};} renderAccTxns(); } function accAllSubCats(){ const set=new Set(); ACC_TXNS.forEach(t=>(t.subCategories||[]).forEach(s=>{if(s)set.add(s);})); return[...set].sort(); } function renderAccTxns(){ const q=(document.getElementById('acc_q')?.value||'').toLowerCase(); const type=document.getElementById('acc_type')?.value||''; const cat=document.getElementById('acc_cat')?.value||''; const projF=document.getElementById('acc_proj')?.value||''; const dateFrom=document.getElementById('acc_date_from')?.value||''; const dateTo=document.getElementById('acc_date_to')?.value||''; const approvalF=document.getElementById('acc_approval')?.value||''; let list=ACC_TXNS.filter(t=>{ if(type&&t.type!==type)return false; if(cat){const cats=[t.category,...(t.projectSplits||[]).map(s=>s.category)].filter(Boolean);if(!cats.includes(cat))return false;} if(projF){const allCodes=[t.projectCode,...(t.projectSplits||[]).map(s=>s.code)].filter(Boolean);if(!allCodes.includes(projF))return false;} if(dateFrom||dateTo){const d=t.submittedDate||t.receivedDate||'';if(dateFrom&&ddateTo)return false;} if(approvalF==='pending'&&(t.type!=='out'||t.approvedDate))return false; if(approvalF==='approved'&&(t.type!=='out'||!t.approvedDate))return false; if(q){const s=[t.id,t.payeeName,t.billNo,t.quotationNo,t.category,t.remarks,...(t.subCategories||[])].join(' ').toLowerCase();if(!s.includes(q))return false;} return true; }).sort((a,b)=>{ const dir=_accSort.asc?1:-1; const getVal=(t,k)=>{ if(k==='id')return t.id||''; if(k==='date')return t.type==='out'?t.submittedDate||'':t.receivedDate||''; if(k==='type')return t.type||''; if(k==='category')return t.category||''; if(k==='payee')return t.payeeName||''; if(k==='bank')return t.bankName||''; if(k==='bill')return t.billNo||t.quotationNo||''; if(k==='amount')return t.type==='out'?(t.submittedAmount||0):(t.amountReceived||0); if(k==='approval')return t.approvedDate||''; return''; }; const va=getVal(a,_accSort.key),vb=getVal(b,_accSort.key); if(typeof va==='number')return(va-vb)*dir; return va.localeCompare(vb)*dir; }); // โ”€โ”€ ID filter (for "Unmatched" drill-down from Account Summary) โ”€โ”€ if(_accIdFilter){list=list.filter(t=>_accIdFilter.includes(t.id));} const tb=document.getElementById('acc_tbody');if(!tb)return; const cnt=document.getElementById('acc_count'); if(cnt)cnt.innerHTML=list.length+' records'+(_accIdFilter?`  โš  Unmatched only  โœ• Clear`:''); if(!list.length){tb.innerHTML=`No records yet ยท Click "+ Add Transaction" to start`;return;} tb.innerHTML=list.map(t=>{ const isOut=t.type==='out'; const date=isOut?t.submittedDate:t.receivedDate; const name=isOut?(t.payeeName||'โ€”'):(t.payeeName||t.quotationNo||'โ€”'); const amt=isOut?(t.submittedAmount||0):(t.amountReceived||0); const typeTag=`${isOut?'โ†‘ Out':'โ†“ In'}`; // Bill / Quot ref with click for bill detail const billRef=isOut&&t.billNo ?`${t.billNo}` :(t.quotationNo||'โ€”'); const _allProjCodes=[...new Set([(t.projectSplits||[]).length?(t.projectSplits).map(s=>s.code):t.projectCode?[t.projectCode]:[]].flat())].filter(Boolean); const projTag=_allProjCodes.map(c=>`๐Ÿ—‚ ${c}`).join(''); // Approval status const approval=isOut ?(t.approvedDate?`โœ… ${t.approvedDate}`:`Pending`) :`โœ… Received`; // Category / split display const _splits=t.projectSplits||[]; const catDisplay=_splits.length>1 ?`
${_splits.map(s=>`
${s.category||'โ€”'}${s.description?`${s.description}`:''}
`).join('')}
` :`
${t.category||'โ€”'}
`; // Sub cats const subCatHtml=(t.subCategories||[]).length?`
${t.subCategories.join(' ยท ')}
`:''; // Attachment indicator const attach=(t.attachmentUrl||t.attachmentName)?`๐Ÿ“Ž `:''; const bankCell=isOut&&(t.bankName||t.bankAccount) ?`
${t.bankName||'โ€”'}
${t.bankAccount||''}
` :'โ€”'; return` ${t.id} ${date||'โ€”'} ${typeTag} ${catDisplay} ${name} ${bankCell}
${billRef}
${projTag} ${RM(amt)} ${approval} ${(t.attachmentUrl||t.attachmentName)?``:'โ€”'} ${isOut&&!t.approvedDate?``:''} `; }).join(''); } // โ”€โ”€ Add / Edit Form โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ let _accFileData=null,_accFileName=null,_accFileLoading=false; let _mfData={}; function accFilterBy(field,value){ closeModal(); const navEl=document.querySelector('.nav-sub-item[onclick*="account_txns"]'); nav('account_txns',navEl); setTimeout(()=>{ if(field==='cat'){const el=document.getElementById('acc_cat');if(el)el.value=value;} else if(field==='proj'){const el=document.getElementById('acc_proj');if(el)el.value=value;} else if(field==='type'){const el=document.getElementById('acc_type');if(el)el.value=value;} else if(field==='q'){const el=document.getElementById('acc_q');if(el)el.value=value;} renderAccTxns(); },50); } let _scIdx=100; let _psiIdx=200; let _accSort={key:'id',asc:false}; let _accSumYear=''; let _accIdFilter=null; // when set, renderAccTxns only shows these IDs let _summaryUnmatchedIds=[]; // populated by accountSummaryPage let _curProject={code:'',txns:[],cl:null,totalIn:0,totalOut:0,pl:0,pending:0}; function accFileChanged(inp){ const file=inp?.files?.[0];if(!file)return; _accFileName=file.name;_accFileData=null;_accFileLoading=true; const hint=document.getElementById('af_file_hint'); const setHint=(msg,col)=>{if(hint){hint.textContent=msg;hint.style.color=col||'var(--muted)';}}; setHint('โณ ่™•็†ไธญ...','var(--muted)'); const isImg=/\.(jpe?g|png)$/i.test(file.name); const reader=new FileReader(); reader.onload=e=>{ const raw=e.target.result; if(isImg){ const img=new Image(); img.onload=()=>{ const MAX=1600,q=0.82; let w=img.naturalWidth,h=img.naturalHeight; if(w>MAX||h>MAX){const r=Math.min(MAX/w,MAX/h);w=Math.round(w*r);h=Math.round(h*r);} const c=document.createElement('canvas');c.width=w;c.height=h; c.getContext('2d').drawImage(img,0,0,w,h); _accFileData=c.toDataURL('image/jpeg',q);_accFileLoading=false; const origKB=Math.round(file.size/1024),newKB=Math.round(_accFileData.length*0.75/1024); setHint(`โœ… ${file.name} โ€” ${origKB}KB โ†’ ~${newKB}KB`,'var(--green)'); }; img.onerror=()=>{_accFileData=raw;_accFileLoading=false;setHint('โœ… '+file.name,'var(--green)');}; img.src=raw; } else { _accFileData=raw;_accFileLoading=false; setHint('โœ… '+file.name+' ('+Math.round(file.size/1024)+'KB)','var(--green)'); } }; reader.onerror=()=>{_accFileLoading=false;setHint('โŒ ่ฎ€ๅ–ๅคฑๆ•—','var(--red)');}; reader.readAsDataURL(file); } function openAccForm(id){ const t=id?ACC_TXNS.find(x=>x.id===id):null; _accFileData=null;_accFileName=null;_accFileLoading=false; _refreshWdDatalist(); const mtEl=document.getElementById('mt'); if(t){ _mfData={type:t.type,cat:t.category,proj:t.projectCode,payee:t.payeeName}; const chips=[]; if(t.type)chips.push(`${t.type==='out'?'โ†‘ OUT':'โ†“ IN'}`); if(t.category)chips.push(`${t.category}`); if(t.projectCode)chips.push(`๐Ÿ— ${t.projectCode}`); if(t.payeeName)chips.push(`${t.payeeName}`); mtEl.innerHTML=`
Edit Transaction #${t.id}
${chips.join('')}
`; }else{mtEl.textContent='New Transaction';} document.getElementById('md').style.maxWidth='720px'; const subCatHtml=(t?.subCategories||[]).map((s,i)=>_scRowHtml(s,'sc_'+i)).join(''); const existingSplits=t?.projectSplits?.length?t.projectSplits :(t?.category||t?.projectCode?[{code:t?.projectCode||'',amount:'',category:t?.category||'',description:t?.workDescription||''}]:[]); const projSplitHtml=existingSplits.map(s=>_psiRowHtml(s.code,s.amount,s.category,s.description)).join(''); document.getElementById('mb').innerHTML=`
Payment Type *
Category *
Attachment
ๆ–นๆกˆไธ€ โ€” ไธŠๅ‚ณๆช”ๆกˆ๏ผˆ่‡ชๅ‹•ๅฃ“็ธฎๅœ–็‰‡๏ผ‰
${t?.attachmentName?``:''}
${t?.attachmentName?'Current: '+t.attachmentName:''}
ๆˆ–
ๆ–นๆกˆไบŒ โ€” ้›ฒ็ซฏ้€ฃ็ต๏ผˆGoogle Drive / Dropbox๏ผ‰
Google Drive โ†’ ๅณ้ตใ€Œๅ–ๅพ—้€ฃ็ตใ€โ†’ ่จญ็‚บใ€Œ็Ÿฅ้“้€ฃ็ต็š„ไบบๅฏๆŸฅ็œ‹ใ€โ†’ ่ฒผไธŠ
Sub Category
${subCatHtml}
${!id?`
`:''}
${id?`
`:''}
`; document.getElementById('mo').classList.add('show'); accFormToggle(); } function exportAccToExcel(){ const q=(document.getElementById('acc_q')?.value||'').toLowerCase(); const type=document.getElementById('acc_type')?.value||''; const cat=document.getElementById('acc_cat')?.value||''; const projF=document.getElementById('acc_proj')?.value||''; const dateFrom=document.getElementById('acc_date_from')?.value||''; const dateTo=document.getElementById('acc_date_to')?.value||''; const list=ACC_TXNS.filter(t=>{ if(type&&t.type!==type)return false; if(cat){const cats=[t.category,...(t.projectSplits||[]).map(s=>s.category)].filter(Boolean);if(!cats.includes(cat))return false;} if(projF){const allCodes=[t.projectCode,...(t.projectSplits||[]).map(s=>s.code)].filter(Boolean);if(!allCodes.includes(projF))return false;} if(dateFrom||dateTo){const d=t.submittedDate||t.receivedDate||'';if(dateFrom&&ddateTo)return false;} if(q){const s=[t.id,t.payeeName,t.billNo,t.quotationNo,t.category,t.remarks,...(t.subCategories||[])].join(' ').toLowerCase();if(!s.includes(q))return false;} return true; }).sort((a,b)=>{ const dir=_accSort.asc?1:-1; const getVal=(t,k)=>{ if(k==='date')return t.type==='out'?t.submittedDate||'':t.receivedDate||''; if(k==='amount')return t.type==='out'?(t.submittedAmount||0):(t.amountReceived||0); if(k==='payee')return t.payeeName||''; return t[k]||''; }; const va=getVal(a,_accSort.key),vb=getVal(b,_accSort.key); if(typeof va==='number')return(va-vb)*dir; return va.localeCompare(vb)*dir; }); if(!list.length){toast('No transactions to export','var(--yellow)');return;} const esc=v=>'"'+String(v==null?'':v).replace(/"/g,'""')+'"'; const headers=['ID','Date','Type','Category','Payee / Party','Bank','Bank Account','Bill No','Quotation No','Work Description','Project Code','Sub Categories','Bill Total (RM)','Submitted Amount (RM)','Amount Received (RM)','Approval Date','Remarks']; const csvRows=list.map(t=>{ const isOut=t.type==='out'; const projCodes=[...new Set([(t.projectSplits||[]).length?(t.projectSplits).map(s=>s.code):t.projectCode?[t.projectCode]:[]].flat())].filter(Boolean).join(', '); return[ t.id, isOut?t.submittedDate||'':t.receivedDate||'', isOut?'Payment Out':'Payment In', t.category||'', isOut?(t.payeeName||''):(t.payeeName||t.quotationNo||''), t.bankName||'', t.bankAccount||'', isOut?t.billNo||'':'', !isOut?t.quotationNo||'':'', t.workDescription||'', projCodes, (t.subCategories||[]).join(', '), isOut?t.billTotalAmount||0:'', isOut?t.submittedAmount||0:'', !isOut?t.amountReceived||0:'', isOut?t.approvedDate||'':'', t.remarks||'' ].map(esc).join(','); }); const csv='๏ปฟ'+[headers.map(esc).join(','),...csvRows].join('\r\n'); const blob=new Blob([csv],{type:'text/csv;charset=utf-8'}); const url=URL.createObjectURL(blob); const a=document.createElement('a'); const now=new Date(); const stamp=now.getFullYear()+'-'+String(now.getMonth()+1).padStart(2,'0')+'-'+String(now.getDate()).padStart(2,'0'); a.href=url;a.download='Inzii_Transactions_'+stamp+'.csv'; document.body.appendChild(a);a.click(); setTimeout(()=>{document.body.removeChild(a);URL.revokeObjectURL(url);},100); toast('โœ… Exported '+list.length+' records','var(--green)'); } function quickApprovePayment(id){ const t=ACC_TXNS.find(x=>x.id===id); if(!t)return; const today=new Date().toISOString().slice(0,10); t.approvedDate=today; saveAccTxns(); renderAccTxns(); toast('โœ… Payment approved: '+today); } function duplicateAccTxn(id){ const orig=ACC_TXNS.find(x=>x.id===id); if(!orig)return; const newId=accNextId(); const dup=Object.assign({},orig,{id:newId,approvedDate:'',attachmentName:'',attachmentData:'',attachmentUrl:''}); ACC_TXNS.push(dup); saveAccTxns(); closeModal(); setTimeout(()=>{openAccForm(newId);toast('Duplicated โ†’ '+newId,'var(--accent)');},120); } function toggleRecurring(cb){ document.getElementById('af_recurring_panel').style.display=cb.checked?'block':'none'; if(cb.checked)calcRecurring(); } function _recDates(start,end,freq,count){ if(!start)return[]; const dates=[]; // Parse start to get the anchor day const [sy,sm,sd]=start.split('-').map(Number); const anchorDay=sd; // keep this day-of-month for monthly/yearly let yr=sy,mo=sm,day=sd; const endD=end?new Date(end+'T00:00:00'):null; const max=Math.min(count||120,120); while(dates.lengthendD)break; dates.push(cur.toISOString().slice(0,10)); // Advance if(freq==='daily'){const n=new Date(cur);n.setDate(n.getDate()+1);yr=n.getFullYear();mo=n.getMonth()+1;day=n.getDate();} else if(freq==='weekly'){const n=new Date(cur);n.setDate(n.getDate()+7);yr=n.getFullYear();mo=n.getMonth()+1;day=n.getDate();} else if(freq==='monthly'){mo++;if(mo>12){mo=1;yr++;}} else if(freq==='yearly'){yr++;} if(!endD&&!count)break; } return dates; } function calcRecurring(){ const start=document.getElementById('af_rec_start')?.value||''; const end=document.getElementById('af_rec_end')?.value||''; const freq=document.getElementById('af_rec_freq')?.value||'monthly'; const countEl=document.getElementById('af_rec_count'); const manualCount=parseInt(countEl?.value)||0; const dates=_recDates(start,end,freq,manualCount||undefined); if(countEl&&!manualCount&&dates.length)countEl.placeholder=dates.length+' payments'; const prev=document.getElementById('af_rec_preview'); if(!prev)return; if(!start){prev.innerHTML='Select start date and frequency to preview schedule';return;} if(!end&&!manualCount){prev.innerHTML='Set End Date or Number of Payments to generate schedule';return;} const amt=parseFloat(document.getElementById('af_subamt')?.value)||0; const total=amt*dates.length; const shown=dates.slice(0,5).map((d,i)=>`#${i+1} ${d}`).join(''); prev.innerHTML=`
${dates.length} payment${dates.length>1?'s':''} scheduled${amt?' ยท RM '+amt.toFixed(2)+' each ยท Total RM '+total.toFixed(2):''}
${shown}${dates.length>5?` +${dates.length-5} moreโ€ฆ`:''}
`; } function calcRecurringFromCount(){ calcRecurring(); // Also update end date based on count + start + freq const start=document.getElementById('af_rec_start')?.value||''; const freq=document.getElementById('af_rec_freq')?.value||'monthly'; const count=parseInt(document.getElementById('af_rec_count')?.value)||0; if(start&&count){ const dates=_recDates(start,null,freq,count); const endEl=document.getElementById('af_rec_end'); if(endEl&&dates.length)endEl.value=dates[dates.length-1]; } } function accFormToggle(){ const type=document.getElementById('af_type')?.value; const out=document.getElementById('af_out');const inp=document.getElementById('af_in'); if(out)out.style.display=type==='out'?'block':'none'; if(inp)inp.style.display=type==='in'?'block':'none'; // For OUT: show expense type selector; for IN: show income category selector const expWrap=document.getElementById('af_expense_type_wrap'); if(expWrap)expWrap.style.display=type==='out'?'block':'none'; const catWrap=document.getElementById('af_cat_wrap'); if(catWrap)catWrap.style.display=type==='in'?'block':'none'; } function _scRowHtml(val,id){ return`
`; } function addSubCatRow(){ _scIdx++; const id='sc_'+_scIdx; const d=document.createElement('div'); d.id=id;d.style.cssText='display:flex;gap:6px;margin-bottom:6px'; d.innerHTML=` `; document.getElementById('af_subcats').appendChild(d); } // โ”€โ”€ Project Split helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function _psiRowHtml(code,amt,category,description){ const id='psi_'+(++_psiIdx); const projOpts=[...new Set(CLIENTS.filter(cl=>cl.projectCode).map(cl=>cl.projectCode))].sort().map(c=>{ const cl=CLIENTS.find(x=>x.projectCode===c); return``; }).join(''); const catOpts=ACC_CATS.map(c=>``).join('')+``; const amtVal=amt!==undefined&&amt!==''?amt:''; return`
Category
Project Code (optional)
Amount (RM)
`; } function accSplitCatChanged(sel){ if(sel.value==='__add__'){ const name=(prompt('Enter new category name:')||'').trim(); if(!name){sel.value='';return;} if(!ACC_CATS.includes(name)){ACC_CATS.push(name);saveAccCats();} sel.innerHTML=''+ACC_CATS.map(c=>``).join('')+``; sel.value=name; } } function addProjSplitRow(){ const container=document.getElementById('af_proj_splits');if(!container)return; const tmp=document.createElement('div'); tmp.innerHTML=_psiRowHtml('','','',''); container.appendChild(tmp.firstElementChild); } function accUpdateSplitTotal(){ const container=document.getElementById('af_proj_splits');if(!container)return; const rows=[...container.children]; const total=rows.reduce((s,row)=>{ const amtEl=row.querySelector('input[type="number"]'); return s+(parseFloat(amtEl?.value||0)||0); },0); const hint=document.getElementById('af_split_total_hint'); if(hint)hint.textContent=rows.length?'ๅˆ่จˆ: RM '+total.toFixed(2):''; } function _getProjSplits(){ const container=document.getElementById('af_proj_splits');if(!container)return[]; return[...container.children].map(row=>{ const catEl=row.querySelector('[id$="_cat"]'); const txtEl=row.querySelector('[id$="_txt"]'); const amtEl=row.querySelector('[id$="_amt"]'); const descEl=row.querySelector('[id$="_desc"]'); return{ category:(catEl?.value==='__add__'?'':catEl?.value||''), code:(txtEl?.value||'').trim(), amount:parseFloat(amtEl?.value||0)||0, description:(descEl?.value||'').trim() }; }).filter(s=>s.category||s.code||s.amount); } function _getSubCats(){ return Array.from(document.getElementById('af_subcats')?.querySelectorAll('input')||[]).map(i=>i.value.trim()).filter(Boolean); } function accCatSelectChanged(sel){ if(sel.value==='__add__'){ const name=(prompt('Enter new category name:')||'').trim(); if(!name){sel.value='';return;} if(!ACC_CATS.includes(name))ACC_CATS.push(name); saveAccCats(); sel.innerHTML=''+accCatOptions(name); sel.value=name; return; } // Auto-fill for Director Withdraw if(sel.value==='Director Withdraw'){ const fset=(id,val)=>{const el=document.getElementById(id);if(el&&!el.value)el.value=val||'';}; // Auto-fill payee with director name from signer settings const dirName=(QUOT_SETTINGS?.signer?.name||'').toUpperCase(); const payeeEl=document.getElementById('af_payee'); if(payeeEl&&!payeeEl.value&&dirName)payeeEl.value=dirName; // Auto-fill bank from last Director Withdraw transaction const lastDir=[...ACC_TXNS] .filter(t=>t.category==='Director Withdraw') .sort((a,b)=>(b.submittedDate||b.date||'').localeCompare(a.submittedDate||a.date||''))[0]; if(lastDir){ const bankSel=document.getElementById('af_bank'); if(bankSel&&lastDir.bankName){ if(![...bankSel.options].find(o=>o.value===lastDir.bankName))bankSel.add(new Option(lastDir.bankName,lastDir.bankName)); bankSel.value=lastDir.bankName; accBankSelectChanged(bankSel); } fset('af_bankacct',lastDir.bankAccount); const expType=document.getElementById('af_expense_type'); if(expType)expType.value='Director Withdraw'; } } } function accSetBankSelect(bankName){ const el=document.getElementById('af_bank');if(!el)return; if(bankName&&!ACC_BANKS.includes(bankName)){ACC_BANKS.push(bankName);saveAccBanks();} el.innerHTML=accBankOptions(bankName);el.value=bankName||''; } function accAutoFillSupplier(sel){ const s=SUPPLIERS.find(x=>x.id===sel.value); if(!s)return; const payee=document.getElementById('af_payee');if(payee)payee.value=s.companyName||''; accSetBankSelect(s.bankName||''); const acct=document.getElementById('af_bankacct');if(acct)acct.value=s.bankAccount||''; // Clear staff selector const stSel=document.getElementById('af_st_sel');if(stSel)stSel.value=''; } function accAutoFillStaff(sel){ const e=HR_EMPS.find(x=>x.empNo===sel.value); if(!e)return; const payee=document.getElementById('af_payee');if(payee)payee.value=e.name||''; accSetBankSelect(e.bank||''); const acct=document.getElementById('af_bankacct');if(acct)acct.value=(e.bankAccount||'').replace(/\*/g,''); // Clear supplier selector to avoid confusion const spSel=document.getElementById('af_sp_sel');if(spSel)spSel.value=''; } function accAutoFillClient(sel){ const cl=CLIENTS.find(x=>x.id===sel.value); if(!cl)return; const payee=document.getElementById('af_payee');if(payee)payee.value=cl.name||''; // Clear supplier-in selector const spIn=document.getElementById('af_sp_in_sel');if(spIn)spIn.value=''; } function accAutoFillSupplierIn(sel){ const s=SUPPLIERS.find(x=>x.id===sel.value); if(!s)return; const payee=document.getElementById('af_payee');if(payee)payee.value=s.companyName||''; // Clear client selector const clSel=document.getElementById('af_cl_sel');if(clSel)clSel.value=''; } function accAutoFillLastTxn(payee){ if(!payee||!payee.trim())return; const typeEl=document.getElementById('af_type'); if(!typeEl||typeEl.value!=='out')return; // Don't overwrite if amounts already entered (editing mode) const existAmt=parseFloat(document.getElementById('af_subamt')?.value)||0; if(existAmt>0)return; const norm=payee.trim().toUpperCase(); const prev=[...ACC_TXNS] .filter(t=>t.type==='out'&&(t.payeeName||'').trim().toUpperCase()===norm) .sort((a,b)=>(b.submittedDate||'').localeCompare(a.submittedDate||''))[0]; if(!prev)return; const fset=(id,val)=>{const el=document.getElementById(id);if(el)el.value=val||'';}; // Expense type / category const expType=document.getElementById('af_expense_type'); if(expType&&prev.category)expType.value=prev.category; // Bank const bankSel=document.getElementById('af_bank'); if(bankSel&&prev.bankName){ if(![...bankSel.options].find(o=>o.value===prev.bankName))bankSel.add(new Option(prev.bankName,prev.bankName)); bankSel.value=prev.bankName; accBankSelectChanged(bankSel); } fset('af_bankacct',prev.bankAccount); fset('af_proj_code',prev.projectCode); fset('af_work_desc_out',prev.workDescription); fset('af_billno',prev.billNo); // Clear amounts โ€” user fills these fset('af_subamt','');fset('af_billtotal',''); toast('โœ“ Auto-filled from last '+norm+' entry','var(--accent)'); } function saveAccForm(id){ if(_accFileLoading){toast('โณ ๆช”ๆกˆ่ฎ€ๅ–ไธญ๏ผŒ่ซ‹็จๅพŒ...','var(--yellow)');setTimeout(()=>saveAccForm(id),300);return;} const type=document.getElementById('af_type')?.value; const _splits=_getProjSplits(); if(!type){toast('Please select Payment Type','var(--yellow)');return;} if(type==='out'&&!document.getElementById('af_expense_type')?.value){toast('Please select Expense Type','var(--yellow)');return;} const existing=id?ACC_TXNS.find(x=>x.id===id):null; const txn={ id:id||accNextId(),type, submittedDate:document.getElementById('af_date')?.value||'', category:type==='out' ?(document.getElementById('af_expense_type')?.value||'') :(document.getElementById('af_cat')?.value||''), subCategories:_getSubCats(), attachmentUrl:document.getElementById('af_attach_url')?.value.trim()||'', attachmentName:_accFileName||existing?.attachmentName||'', payeeName:(document.getElementById('af_payee')?.value||'').toUpperCase().trim(), remarks:(document.getElementById('af_remarks')?.value||'').toUpperCase().trim(), workDescription:type==='out'?(document.getElementById('af_work_desc_out')?.value||'').toUpperCase().trim():(document.getElementById('af_work_desc_in')?.value||'').toUpperCase().trim(), projectSplits:[], projectCode:type==='out'?(document.getElementById('af_proj_code')?.value||'').toUpperCase().trim():(document.getElementById('af_proj_code_in')?.value||'').toUpperCase().trim()||(_splits[0]?.code||''), // Out bankName:document.getElementById('af_bank')?.value||'', bankAccount:document.getElementById('af_bankacct')?.value||'', billNo:(document.getElementById('af_billno')?.value||'').toUpperCase().trim(), billTotalAmount:parseFloat(document.getElementById('af_billtotal')?.value||0)||0, submittedAmount:parseFloat(document.getElementById('af_subamt')?.value||0)||0, approvedDate:document.getElementById('af_approved')?.value||'', // In quotationNo:document.getElementById('af_quotno')?.value||'', projectAmount:parseFloat(document.getElementById('af_projamt')?.value||0)||0, amountReceived:parseFloat(document.getElementById('af_recamt')?.value||0)||0, receivedDate:document.getElementById('af_recdate')?.value||'', createdAt:existing?.createdAt||new Date().toISOString(), }; // โ”€โ”€ Recurring Payment โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ if(!id&&document.getElementById('af_recurring')?.checked){ const recStart=document.getElementById('af_rec_start')?.value||''; const recEnd=document.getElementById('af_rec_end')?.value||''; const recFreq=document.getElementById('af_rec_freq')?.value||'monthly'; const recCount=parseInt(document.getElementById('af_rec_count')?.value)||0; const recRef=(document.getElementById('af_rec_ref')?.value||'').toUpperCase().trim(); const recDetails=document.getElementById('af_rec_details')?.value||''; const recDates=_recDates(recStart,recEnd,recFreq,recCount||undefined); if(!recDates.length){toast('No dates generated โ€” set Start Date and End Date or Number of Payments','var(--yellow)');return;} recDates.forEach((date,i)=>{ const seq=String(i+1).padStart(2,'0'); const billNo=recRef?(recRef+'-'+seq):(txn.billNo?txn.billNo+'-'+seq:''); const rem=[recDetails,txn.remarks].filter(Boolean).join(' ยท '); const today=new Date().toISOString().slice(0,10); const approvedDate=(txn.type==='out'&&date<=today)?date:''; // auto-approve past/today dates ACC_TXNS.push({...txn,id:accNextId(),submittedDate:txn.type==='out'?date:'',receivedDate:txn.type==='in'?date:'',billNo,remarks:rem,approvedDate,isRecurring:true}); }); saveAccTxns(); // Auto-add supplier for OUT if(type==='out'&&txn.payeeName){ const norm=txn.payeeName.trim().toUpperCase(); if(!SUPPLIERS.find(s=>(s.companyName||'').trim().toUpperCase()===norm)){ SUPPLIERS.push({id:supplierNextId(),companyName:txn.payeeName.trim(),bankName:txn.bankName||'',bankAccount:txn.bankAccount||'',companyPhone:'',contactPerson:'',email:'',regNo:'',tinNo:'',sstNo:'',irbMsicCode:'',createdAt:new Date().toISOString()}); saveSuppliers(); } } _accFileData=null;_accFileName=null;_accFileLoading=false; closeModal();toast('โœ… Created '+recDates.length+' recurring transactions','var(--green)');renderAccTxns();return; } // โ”€โ”€ Auto-save new work description โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ _accSaveNewWd(txn.workDescription); // โ”€โ”€ Single Transaction โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ if(id){const i=ACC_TXNS.findIndex(x=>x.id===id);if(i>=0)ACC_TXNS[i]=txn;} else ACC_TXNS.push(txn); const fd=_accFileData,fn=_accFileName; _accFileData=null;_accFileName=null;_accFileLoading=false; if(fd&&fn){ // Store in BOTH localStorage (backup) AND IndexedDB txn.attachmentData=fd; const _ai=ACC_TXNS.findIndex(x=>x.id===txn.id); if(_ai>=0)ACC_TXNS[_ai]=txn; idbSaveFile(txn.id,fn,fd).catch(()=>{}); } saveAccTxns(); // โ”€โ”€ Auto-add payee to Supplier Details for OUT transactions โ”€โ”€ if(type==='out'&&txn.payeeName){ const norm=txn.payeeName.trim().toUpperCase(); const existing=SUPPLIERS.find(s=>(s.companyName||'').trim().toUpperCase()===norm); if(!existing){ if(txn.bankName&&!ACC_BANKS.includes(txn.bankName)){ACC_BANKS.push(txn.bankName);saveAccBanks();} SUPPLIERS.push({id:supplierNextId(),companyName:txn.payeeName.trim(),bankName:txn.bankName||'',bankAccount:txn.bankAccount||'',companyPhone:'',contactPerson:'',email:'',regNo:'',tinNo:'',sstNo:'',irbMsicCode:'',createdAt:new Date().toISOString()}); saveSuppliers(); const _spOpts=''+SUPPLIERS.map(s=>``).join(''); const spSel=document.getElementById('af_sp_sel');if(spSel)spSel.innerHTML=_spOpts; const spInSel=document.getElementById('af_sp_in_sel');if(spInSel)spInSel.innerHTML=_spOpts; } else if(!existing.bankName&&txn.bankName){ existing.bankName=txn.bankName;if(txn.bankAccount)existing.bankAccount=txn.bankAccount; saveSuppliers(); } } closeModal();toast('Saved โœ“','var(--green)');renderAccTxns(); } function deleteAccFileOnly(id){ if(!confirm('Delete the attached file for this transaction?'))return; const t=ACC_TXNS.find(x=>x.id===id); if(!t)return; t.attachmentName='';t.attachmentData='';t.attachmentUrl=''; idbDeleteFile(id).catch(()=>{}); saveAccTxns(); // Refresh attachment hint and buttons in the currently open form const hint=document.getElementById('af_file_hint'); if(hint)hint.textContent=''; const fileRow=document.getElementById('af_attach_row'); if(fileRow)fileRow.innerHTML=``; const urlEl=document.getElementById('af_attach_url'); if(urlEl)urlEl.value=''; toast('๐Ÿ—‘ File deleted','var(--red)'); } function deleteAccTxn(id){ if(!confirm('Delete this transaction?'))return; ACC_TXNS=ACC_TXNS.filter(x=>x.id!==id); idbDeleteFile(id).catch(()=>{}); saveAccTxns();renderAccTxns(); } function openAccDetail(id){openAccForm(id);} function viewAccAttachment(id){ const t=ACC_TXNS.find(x=>x.id===id); // Priority 1: cloud URL if(t?.attachmentUrl){window.open(t.attachmentUrl,'_blank');return;} // Priority 2: IndexedDB uploaded file if(t?.attachmentName){ idbGetFile(id).then(rec=>{ let fileData=rec?.fileData||t.attachmentData; if(!fileData){ try{ const raw=JSON.parse(localStorage.getItem('inzii_acc_txns')||'[]'); fileData=raw.find(x=>x.id===id)?.attachmentData||''; }catch(e){} } if(!fileData){toast('้™„ไปถๆ‰พไธๅˆฐ โ€” ่ซ‹้‡ๆ–ฐไธŠๅ‚ณๆˆ–ๆ”น็”จ้›ฒ็ซฏ้€ฃ็ต','var(--yellow)');return;} if(!rec?.fileData&&fileData)idbSaveFile(id,t.attachmentName,fileData).catch(()=>{}); const w=window.open('','_blank');if(!w)return; const isPdf=t.attachmentName.toLowerCase().endsWith('.pdf'); if(isPdf){w.document.write(``);} else{w.document.write(``);} w.document.close(); }).catch(()=>toast('Could not load attachment','var(--red)')); return; } toast('No attachment','var(--yellow)'); } // โ”€โ”€ Account Summary โ€” Drill-down Modal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function openSummaryModal(title,isIn,idStr){ const ids=(idStr||'').split(',').filter(Boolean); const txns=ACC_TXNS.filter(t=>ids.includes(t.id)).sort((a,b)=>{ const da=a.type==='out'?a.submittedDate||'':a.receivedDate||''; const db=b.type==='out'?b.submittedDate||'':b.receivedDate||''; return db.localeCompare(da); }); if(!txns.length)return; const total=txns.reduce((s,t)=>s+(isIn?t.amountReceived||0:t.submittedAmount||0),0); document.getElementById('mt').innerHTML=`
${title}
${txns.length} records  ยท  Total: ${RM(total)}
`; document.getElementById('md').style.maxWidth='860px'; const projCodes=[...new Set(txns.map(t=>t.projectCode||(t.projectSplits||[])[0]?.code||'').filter(Boolean))]; const showProj=projCodes.length>0; document.getElementById('mb').innerHTML=` ${showProj?'':''} ${txns.map(t=>{ const date=t.type==='out'?t.submittedDate||'':t.receivedDate||''; const amt=isIn?t.amountReceived||0:t.submittedAmount||0; const approved=isIn?((t.amountReceived||0)>0||!!t.approvedDate):!!t.approvedDate; const statusLabel=approved?(isIn?'Received':'Approved'):(isIn?'Pending':'Pending Approval'); const statusColor=approved?'green':isIn?'yellow':'yellow'; const proj=t.projectCode||(t.projectSplits||[])[0]?.code||''; return` ${showProj?``:''} `; }).join('')}
IDDatePayee / PartyProjectRemarks AmountStatus
${t.id} ${date||'โ€”'} ${t.payeeName||'โ€”'}${proj||'โ€”'}${t.remarks||t.workDescription||'โ€”'} ${RM(amt)} ${statusLabel}
`; document.getElementById('mo').classList.add('show'); } // โ”€โ”€ Payee Detail Modal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function openPayeeDetail(payeeName){ payeeName=(payeeName||'').replace(/"/g,'"'); if(!payeeName||payeeName==='โ€”')return; const txns=ACC_TXNS.filter(t=>(t.payeeName||t.quotationNo||'')===payeeName) .sort((a,b)=>{ const da=a.type==='out'?a.submittedDate:a.receivedDate; const db=b.type==='out'?b.submittedDate:b.receivedDate; return(db||'').localeCompare(da||''); }); if(!txns.length){toast('No records for '+payeeName,'var(--yellow)');return;} const outTxns=txns.filter(t=>t.type==='out'); const inTxns=txns.filter(t=>t.type==='in'); const totalOut=outTxns.reduce((s,t)=>s+(t.submittedAmount||0),0); const totalIn=inTxns.reduce((s,t)=>s+(t.amountReceived||0),0); const approvedOut=outTxns.filter(t=>t.approvedDate).reduce((s,t)=>s+(t.submittedAmount||0),0); const pendingOut=outTxns.filter(t=>!t.approvedDate).reduce((s,t)=>s+(t.submittedAmount||0),0); _mfData.payee=payeeName; document.getElementById('mt').innerHTML=`
${payeeName}
โ†‘โ†“ Filter Transactions
`; document.getElementById('md').style.maxWidth='780px'; document.getElementById('mb').innerHTML=`
${[['Total Out',RM(totalOut),'var(--red)'],['Total In',RM(totalIn),'var(--green)'],['Approved Out',RM(approvedOut),'var(--green)'],['Pending',RM(pendingOut),'var(--yellow)']].map(([l,v,col])=>`
${l}
${v}
`).join('')}
All Transactions (${txns.length})
${txns.map(t=>{ const isOut=t.type==='out'; const date=isOut?t.submittedDate:t.receivedDate; const amt=isOut?(t.submittedAmount||0):(t.amountReceived||0); const ref=isOut?(t.billNo||'โ€”'):(t.quotationNo||'โ€”'); const appr=isOut ?(t.approvedDate?`โœ… ${t.approvedDate}`:`Pending`) :`โœ… Received`; return``; }).join('')}
DateTypeCategory Project CodeBill / Quot AmountApproval
${date||'โ€”'} ${isOut?'โ†‘ Out':'โ†“ In'} ${(t.projectSplits||[]).length>1?(t.projectSplits).map(s=>`
${s.category||'โ€”'}${s.description?` ${s.description}`:''}
`).join(''):(t.category||'โ€”')}${t.remarks?`
${t.remarks}
`:''}
${t.projectCode?`${t.projectCode}`:'โ€”'} ${(t.type==='out'&&t.billNo)?`${t.billNo}`:(ref==='โ€”'?'โ€”':ref)}${(()=>{const sp=t.projectSplits||[];if(sp.length>1){const descs=sp.filter(s=>s.description).map(s=>`
${s.description}
`).join('');return descs||'';}const wd=t.workDescription;return(wd&&wd!=='__add__')?`
${wd}
`:'';})()}
${RM(amt)} ${appr}
`; document.getElementById('mo').classList.add('show'); } // โ”€โ”€ Bill Status Detail Modal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function openAccBillDetail(billNo){ const payments=ACC_TXNS.filter(t=>t.type==='out'&&t.billNo===billNo).sort((a,b)=>(a.submittedDate||'').localeCompare(b.submittedDate||'')); if(!payments.length)return; const billTotal=Math.max(...payments.map(t=>t.billTotalAmount||0)); const totalSubmitted=payments.reduce((s,t)=>s+(t.submittedAmount||0),0); const totalApproved=payments.filter(t=>t.approvedDate).reduce((s,t)=>s+(t.submittedAmount||0),0); const balance=Math.max(0,billTotal-totalApproved); const pct=billTotal>0?Math.min(100,(totalApproved/billTotal*100)).toFixed(1):0; const pending=Math.max(0,totalSubmitted-totalApproved); const statusColor=balance===0?'green':totalApproved>0?'yellow':'red'; const statusLabel=balance===0?'Fully Paid':totalApproved>0?'Partially Paid':'Pending'; _mfData.bill=billNo; document.getElementById('mt').innerHTML=`
Bill: ${billNo}
โ†‘โ†“ Filter Transactions
`; document.getElementById('md').style.maxWidth='620px'; document.getElementById('mb').innerHTML=`
๐Ÿ“„ ${billNo}
${statusLabel}
${billTotal>0?`
Payment Progress${pct}% Approved
${pending>0&&billTotal>0?`
`:''}
โ–  Approved ${RM(totalApproved)} ${pending>0?`โ–  Pending ${RM(pending)}`:''} โ–  Outstanding ${RM(balance)}
`:''}
${[['Bill Total',RM(billTotal),'var(--accent)'],['Submitted',RM(totalSubmitted),'var(--text)'],['Approved',RM(totalApproved),'var(--green)'],['Outstanding',RM(balance),balance>0?'var(--red)':'var(--green)']].map(([l,v,col])=>`
${l}
${v}
`).join('')}
Payment History (${payments.length})
${(()=>{let runPaid=0;return payments.map((t,i)=>{ const approved=!!t.approvedDate; const amt=t.submittedAmount||0; if(approved)runPaid+=amt; const runBal=Math.max(0,billTotal-runPaid); const isLast=i===payments.length-1; return`
${approved?'โœ“':'โณ'}
${!isLast?`
`:''}
Payment #${i+1} ${approved?'Approved':'Pending Approval'}
โˆ’ ${RM(amt)}
๐Ÿ“… Submitted: ${t.submittedDate||'โ€”'} ${approved?`โœ… Approved: ${t.approvedDate}`:'โš  Not yet approved โ€” still outstanding'}
${t.payeeName?`
๐Ÿ‘ค ${t.payeeName}${t.bankName?` ยท ๐Ÿฆ ${t.bankName}${t.bankAccount?' ('+t.bankAccount+')':''}`:''}
`:''} ${t.remarks?`
๐Ÿ’ฌ ${t.remarks}
`:''} ${(t.attachmentUrl||t.attachmentName)?`
`:''}
Running Balance After This Payment ${runBal>0?RM(runBal)+' outstanding':'Fully Paid โœ“'}
`; }).join('');})()}
`; document.getElementById('mo').classList.add('show'); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ CLIENT DETAILS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function clientsPage(){ return`
ID Name Contact No Address Project Code
`; } function renderClients(){ const q=(document.getElementById('cl_q')?.value||'').toLowerCase(); const list=CLIENTS.filter(cl=>{ if(!q)return true; return[cl.name,cl.contactNo,cl.address,cl.projectCode].join(' ').toLowerCase().includes(q); }); const tb=document.getElementById('cl_tbody');if(!tb)return; const cnt=document.getElementById('cl_count');if(cnt)cnt.textContent=list.length+' clients'; if(!list.length){tb.innerHTML=`No clients yet ยท Click "+ Add Client" to start`;return;} tb.innerHTML=list.map(cl=>` ${cl.id}
${cl.name||'โ€”'}
${cl.contactNo||'โ€”'} ${cl.address||'โ€”'} ${cl.projectCode?cl.projectCode.split(',').map(p=>`${p.trim()}`).join(' '):'โ€”'} `).join(''); } function openClientForm(id){ const cl=id?CLIENTS.find(x=>x.id===id):null; if(cl){ const projCodes=(cl.projectCode||'').split(',').map(p=>p.trim()).filter(Boolean); const projChips=projCodes.map(c=>`๐Ÿ— ${c}`).join(''); document.getElementById('mt').innerHTML=`
Edit Client โ€” ${cl.name}
${projChips}
`; }else document.getElementById('mt').textContent='New Client'; document.getElementById('md').style.maxWidth='560px'; document.getElementById('mb').innerHTML=`
Name *
Contact No
Project Code
Address
Remarks
`; document.getElementById('mo').classList.add('show'); } function saveClient(id){ const name=document.getElementById('clf_name')?.value.trim(); if(!name){toast('Name is required','var(--yellow)');return;} const cl={ id:id||clientNextId(), name, contactNo:document.getElementById('clf_contact')?.value.trim()||'', address:document.getElementById('clf_addr')?.value.trim()||'', projectCode:document.getElementById('clf_proj')?.value.trim()||'', remarks:document.getElementById('clf_remarks')?.value.trim()||'', createdAt:(id?CLIENTS.find(x=>x.id===id)?.createdAt:null)||new Date().toISOString(), }; if(id){const i=CLIENTS.findIndex(x=>x.id===id);if(i>=0)CLIENTS[i]=cl;} else CLIENTS.push(cl); saveClients();closeModal();toast('Saved โœ“','var(--green)');renderClients(); } function deleteClient(id){ if(!confirm('Delete this client?'))return; CLIENTS=CLIENTS.filter(x=>x.id!==id); saveClients();renderClients(); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ SUPPLIER DETAILS โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function importStaffAsSuppliers(){ const active=HR_EMPS.filter(e=>!e.resigned); let added=0,skipped=0; active.forEach(e=>{ // Check if already in suppliers by matching name (IC/empNo as nricNo) const exists=SUPPLIERS.find(s=>s.nricNo===e.ic||s.companyName===e.name); if(exists){skipped++;return;} const bankName=e.bank||''; if(bankName&&!ACC_BANKS.includes(bankName)){ACC_BANKS.push(bankName);saveAccBanks();} SUPPLIERS.push({ id:supplierNextId(), companyName:e.name, bankName:bankName, bankAccount:(e.bankAccount||'').replace(/\*/g,''), companyPhone:e.phone||'', companyEmail:e.email||'', companyAddress:e.address||'', businessActivities:'Staff / Internal', tinNo:e.taxNo||'', ssmNo:'', nricNo:e.ic||'', sstNo:'', irbMsicCode:'', }); added++; }); saveSuppliers(); renderSuppliers(); // Refresh supplier dropdowns in open form if any const _spOpts2=''+SUPPLIERS.map(s=>``).join(''); const spSel=document.getElementById('af_sp_sel');if(spSel)spSel.innerHTML=_spOpts2; const spInSel=document.getElementById('af_sp_in_sel');if(spInSel)spInSel.innerHTML=_spOpts2; toast(`Imported ${added} staff ยท ${skipped} already exist`,'var(--green)'); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // โ”€โ”€ PROJECT OVERVIEW โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function projectOverviewPage(){ return`
Project CodeClientContact IncomeExpenses P&L
`; } // Returns all project codes across all transactions (including splits) function _allTxnProjCodes(){ const set=new Set(); ACC_TXNS.forEach(t=>{ if(t.projectCode)set.add(t.projectCode); (t.projectSplits||[]).forEach(s=>{if(s.code)set.add(s.code);}); }); return set; } // Returns all transactions that involve a given project code function _txnsForProj(code){ return ACC_TXNS.filter(t=>t.projectCode===code||(t.projectSplits||[]).some(s=>s.code===code)); } // Returns the effective OUT amount for a transaction scoped to a project code function _outAmtForProj(t,code){ const splits=t.projectSplits||[]; if(splits.length){ const s=splits.find(x=>x.code===code); return s?s.amount:0; } return t.submittedAmount||0; } function exportProjectOverview(){ const q=(document.getElementById("pov_q")?.value||"").toLowerCase(); const allCodes=new Set([ ...CLIENTS.filter(cl=>cl.projectCode).map(cl=>cl.projectCode), ..._allTxnProjCodes() ]); const projects=[...allCodes].map(code=>{ const cl=CLIENTS.find(x=>x.projectCode===code)||null; const txns=_txnsForProj(code); const income=txns.filter(t=>t.type==="in").reduce((s,t)=>s+(t.amountReceived||0),0); const expenses=txns.filter(t=>t.type==="out").reduce((s,t)=>s+_outAmtForProj(t,code),0); const pending=txns.filter(t=>t.type==="out"&&!t.approvedDate).reduce((s,t)=>s+_outAmtForProj(t,code),0); return{code,cl,income,expenses,pl:income-expenses,pending,txnCount:txns.length}; }).filter(p=>!q||(p.code+" "+(p.cl?.name||"")).toLowerCase().includes(q)) .sort((a,b)=>a.code.localeCompare(b.code)); // Build CSV const headers=["Project Code","Client Name","Contact No","Address","Total Income (RM)","Total Expenses (RM)","P&L (RM)","Pending Approval (RM)","No. of Transactions"]; const rows=projects.map(p=>[ p.code, p.cl?.name||"", p.cl?.contactNo||"", (p.cl?.address||"").replace(/,/g," "), p.income.toFixed(2), p.expenses.toFixed(2), p.pl.toFixed(2), p.pending.toFixed(2), p.txnCount, ]); const csv=[headers,...rows].map(r=>r.map(v=>`"${String(v).replace(/"/g,'""')}"`).join(",")).join("\n"); const blob=new Blob(["\uFEFF"+csv],{type:"text/csv;charset=utf-8;"}); const url=URL.createObjectURL(blob); const a=document.createElement("a"); a.href=url; a.download="Project_Overview_"+new Date().toISOString().slice(0,10)+".csv"; a.click(); URL.revokeObjectURL(url); toast("Exported "+projects.length+" projects","var(--green)"); } function renderProjectOverview(){ const q=(document.getElementById("pov_q")?.value||"").toLowerCase(); const allCodes=new Set([ ...CLIENTS.filter(cl=>cl.projectCode).map(cl=>cl.projectCode), ..._allTxnProjCodes() ]); let projects=[...allCodes].map(code=>{ const cl=CLIENTS.find(x=>x.projectCode===code)||null; const txns=_txnsForProj(code); const income=txns.filter(t=>t.type==="in").reduce((s,t)=>s+(t.amountReceived||0),0); const expenses=txns.filter(t=>t.type==="out").reduce((s,t)=>s+_outAmtForProj(t,code),0); return{code,cl,txns,income,expenses,pl:income-expenses}; }).filter(p=>!q||(p.code+" "+(p.cl?.name||"")).toLowerCase().includes(q)) .sort((a,b)=>a.code.localeCompare(b.code)); const tb=document.getElementById("pov_tbody");if(!tb)return; const cnt=document.getElementById("pov_count");if(cnt)cnt.textContent=projects.length+" projects"; if(!projects.length){tb.innerHTML=`No projects found`;return;} tb.innerHTML=projects.map(p=>{ const plColor=p.pl>0?"var(--green)":p.pl<0?"var(--red)":"var(--muted)"; return` ${p.code} ${p.cl?.name||"โ€”"} ${p.cl?.contactNo||"โ€”"} ${p.income>0?RM(p.income):"โ€”"} ${p.expenses>0?RM(p.expenses):"โ€”"} ${p.income||p.expenses?RM(p.pl):"โ€”"} `; }).join(""); } function openProjectDetail(code){ const cl=CLIENTS.find(x=>x.projectCode===code)||null; const txns=_txnsForProj(code).sort((a,b)=>{ const da=a.type==="out"?a.submittedDate:a.receivedDate; const db=b.type==="out"?b.submittedDate:b.receivedDate; return(db||"").localeCompare(da||""); }); const inTxns=txns.filter(t=>t.type==="in"); const outTxns=txns.filter(t=>t.type==="out"); const totalIn=inTxns.reduce((s,t)=>s+(t.amountReceived||0),0); const totalOut=outTxns.reduce((s,t)=>s+_outAmtForProj(t,code),0); const pl=totalIn-totalOut; const pending=outTxns.filter(t=>!t.approvedDate).reduce((s,t)=>s+_outAmtForProj(t,code),0); _curProject={code,txns,cl,totalIn,totalOut,pl,pending}; _mfData.proj=code; document.getElementById("mt").innerHTML=`
Project: ${code}
โ†‘โ†“ Filter Transactions
`; document.getElementById("md").style.maxWidth="750px"; document.getElementById("mb").innerHTML=`
${cl?`
${cl.name}
${cl.contactNo?`
๐Ÿ“ž ${cl.contactNo}
`:""} ${cl.address?`
๐Ÿ“ ${cl.address}
`:""}
${code}
`:`
No client record linked to ${code}
`}
${[["Income",RM(totalIn),"var(--green)"],["Expenses",RM(totalOut),"var(--red)"],["P&L",RM(pl),pl>=0?"var(--green)":"var(--red)"],["Pending",RM(pending),"var(--yellow)"]].map(([l,v,col])=>`
${l}
${v}
`).join("")}
${(()=>{ if(!inTxns.length)return''; const byCat={}; inTxns.forEach(t=>{const c=t.category||'Other';byCat[c]=(byCat[c]||0)+(t.amountReceived||0);}); const rows=Object.entries(byCat).map(([c,a])=>`
${c} ${RM(a)}
`).join(''); return`
๐Ÿ’ฐ Payment In Breakdown
${rows}
`; })()}
All Transactions (${txns.length})
${txns.length?`
${txns.map(t=>{ const isOut=t.type==="out"; const date=isOut?t.submittedDate:t.receivedDate; const amt=isOut?_outAmtForProj(t,code):(t.amountReceived||0); const isSplit=isOut&&(t.projectSplits||[]).length>1; const appr=isOut?(t.approvedDate?`โœ… ${t.approvedDate}`:`Pending`):`โœ… Received`; return``; }).join("")}
DateTypeBill NoWork DescriptionPayee / PartyAmountApproval
${date||"โ€”"} ${isOut?"โ†‘ Out":"โ†“ In"} ${(t.type==='out'&&t.billNo)?`${t.billNo}`:t.quotationNo?`${t.quotationNo}`:"โ€”"} ${(()=>{const sp=t.projectSplits||[];if(sp.length>1)return sp.filter(s=>s.description).map(s=>`
${s.description}
`).join('')||"โ€”";const wd=t.workDescription;return(wd&&wd!=='__add__')?wd:"โ€”";})()}
${t.payeeName?`${t.payeeName}`:'โ€”'} ${RM(amt)}${isSplit?`
of ${RM(t.submittedAmount||0)}
`:""}
${appr}
`:"
No transactions for this project yet
"}
`; document.getElementById("mo").classList.add("show"); } function exportProjectCSV(code,txns,cl){ const headers=["Date","Type","Category","Work Description","Payee / Party","Bank","Account No","Bill / Quot No","Amount (RM)","Approval Date","Project Code","Remarks"]; const rows=txns.map(t=>{ const isOut=t.type==="out"; return[ isOut?t.submittedDate||"":t.receivedDate||"", isOut?"Payment Out":"Payment In", t.category||"", t.workDescription||"", t.payeeName||"", t.bankName||"", t.bankAccount||"", isOut?(t.billNo||""):(t.quotationNo||""), isOut?(t.submittedAmount||0).toFixed(2):(t.amountReceived||0).toFixed(2), t.approvedDate||"", t.projectCode||"", t.remarks||"", ]; }); const csv=[headers,...rows].map(r=>r.map(v=>`"${String(v).replace(/"/g,'""')}"`).join(",")).join("\n"); const blob=new Blob(["\uFEFF"+csv],{type:"text/csv;charset=utf-8;"}); const url=URL.createObjectURL(blob); const a=document.createElement("a"); a.href=url; a.download="Project_"+code+"_"+new Date().toISOString().slice(0,10)+".csv"; a.click(); URL.revokeObjectURL(url); toast("Exported "+txns.length+" transactions","var(--green)"); } function exportProjectPDF(code,txns,cl,totalIn,totalOut,pl,pending){ const inTxns=txns.filter(t=>t.type==="in"); const outTxns=txns.filter(t=>t.type==="out"); const rows=txns.map(t=>{ const isOut=t.type==="out"; const date=isOut?t.submittedDate||"โ€”":t.receivedDate||"โ€”"; const amt=isOut?(t.submittedAmount||0):(t.amountReceived||0); const appr=t.approvedDate||"Pending"; const color=isOut?"#e53e3e":"#38a169"; return` ${date} ${isOut?"โ†‘ Out":"โ†“ In"} ${t.category||"โ€”"} ${t.workDescription||"โ€”"} ${t.payeeName||"โ€”"} RM ${amt.toFixed(2)} ${appr} `; }).join(""); const html=`Project ${code}

Project Report

${code}
${cl?`
Client: ${cl.name}
${cl.contactNo?"
Contact: "+cl.contactNo+"
":""} ${cl.address?"
Address: "+cl.address+"
":""}
`:""}
Income
RM ${totalIn.toFixed(2)}
Expenses
RM ${totalOut.toFixed(2)}
P&L
RM ${pl.toFixed(2)}
Pending
RM ${pending.toFixed(2)}
${rows}
DateTypeCategoryWork DescriptionPayee / PartyAmountApproval
`; const w=window.open("","_blank","width=960,height=700"); if(!w){toast("Please allow pop-ups","var(--yellow)");return;} w.document.write(html);w.document.close(); setTimeout(()=>w.print(),400); } function suppliersPage(){ return`
Company / Name Bank Bank Account No
`; } function renderSuppliers(){ const q=(document.getElementById('sp_q')?.value||'').toLowerCase(); const list=SUPPLIERS.filter(s=>{ if(!q)return true; return[s.companyName,s.tinNo,s.ssmNo,s.nricNo,s.companyEmail,s.companyPhone].join(' ').toLowerCase().includes(q); }); const tb=document.getElementById('sp_tbody');if(!tb)return; const cnt=document.getElementById('sp_count');if(cnt)cnt.textContent=list.length+' suppliers'; if(!list.length){tb.innerHTML=`No suppliers yet ยท Click "+ Add Supplier" to start`;return;} tb.innerHTML=list.map(s=>`
${s.companyName||'โ€”'}
${s.bankName||'โ€”'} ${s.bankAccount||'โ€”'} `).join(''); } function openSupplierForm(id){ const s=id?SUPPLIERS.find(x=>x.id===id):null; if(s){_mfData.payee=s.companyName||'';document.getElementById('mt').innerHTML=`
Edit Supplier โ€” ${s.companyName||s.id}
โ†‘โ†“ View Transactions
`;} else document.getElementById('mt').textContent='New Supplier'; document.getElementById('md').style.maxWidth='680px'; document.getElementById('mb').innerHTML=`
Company Information
Company Name *
Bank Name
Bank Account Number
Company Phone No
Company Email
Company Address
Business Activities
Registration Numbers
TIN Number
SSM Number
NRIC Number
SST Number
IRB MSIC Code
`; document.getElementById('mo').classList.add('show'); } function saveSupplier(id){ const name=document.getElementById('spf_name')?.value.trim(); if(!name){toast('Company Name is required','var(--yellow)');return;} const s={ id:id||supplierNextId(), companyName:name, bankName:document.getElementById('spf_bankname')?.value.trim()||'', bankAccount:document.getElementById('spf_bankacct')?.value.trim()||'', companyPhone:document.getElementById('spf_phone')?.value.trim()||'', companyEmail:document.getElementById('spf_email')?.value.trim()||'', companyAddress:document.getElementById('spf_addr')?.value.trim()||'', businessActivities:document.getElementById('spf_biz')?.value.trim()||'', tinNo:document.getElementById('spf_tin')?.value.trim()||'', ssmNo:document.getElementById('spf_ssm')?.value.trim()||'', nricNo:document.getElementById('spf_nric')?.value.trim()||'', sstNo:document.getElementById('spf_sst')?.value.trim()||'', irbMsicCode:document.getElementById('spf_msic')?.value.trim()||'', createdAt:(id?SUPPLIERS.find(x=>x.id===id)?.createdAt:null)||new Date().toISOString(), }; if(id){const i=SUPPLIERS.findIndex(x=>x.id===id);if(i>=0)SUPPLIERS[i]=s;} else SUPPLIERS.push(s); saveSuppliers();closeModal();toast('Saved โœ“','var(--green)');renderSuppliers(); } function deleteSupplier(id){ if(!confirm('Delete this supplier?'))return; SUPPLIERS=SUPPLIERS.filter(x=>x.id!==id); saveSuppliers();renderSuppliers(); } // Run seed on load seedBankPaymentRecords(); seedSalaryExpenses2026(); seedMiscTransactions2026(); seedJan2026Expenses(); seedClients(); // Migrate any legacy attachmentData from localStorage โ†’ IndexedDB migrateAttachmentsToIDB(); // โ”€โ”€ Login gate โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ // โ”€โ”€ Logo title init & edit โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function(){ const t=localStorage.getItem('inzii_logo_title'); const s=localStorage.getItem('inzii_logo_sub'); if(t){const el=document.getElementById('logo-title-text');if(el)el.textContent=t;} if(s){const el=document.getElementById('logo-sub-text');if(el)el.textContent=s;} })(); // โ”€โ”€ Seed Jan 2026 transactions (one-time) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function seedJan2026(){ if(localStorage.getItem('inzii_seeded_jan2026'))return; function mk(id,type,date,payee,cat,proj,bank,acc,total,sub,recv,bill,wd,rem,approved,splits){ return{id,type,submittedDate:date,receivedDate:type==='in'?date:'',payeeName:payee||'',category:cat,projectCode:proj||'',bankName:bank||'',bankAccount:acc||'',totalAmount:total||0,submittedAmount:sub||0,amountReceived:recv||0,billNo:bill||'',workDescription:wd||'',remarks:rem||'',subCategories:[],approvedDate:approved||'',projectSplits:splits||[]}; } function sp(code,amt,cat,desc){return{code:code||'',amount:amt||0,category:cat||'',description:desc||''};} const rows=[ mk('AT2001','out','2026-01-16','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1070','OCBC Bank','7161154406',4000,4000,0,'QUO2510/0363','','','2026-01-22',[sp('PJ1070',4000,'Painting Work','')]), mk('AT2002','out','2026-01-16','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1063','Hong Leong Bank','19701001505',41085,8217,0,'20250034','','','2026-02-05',[sp('PJ1063',8217,'M/E Work','')]), mk('AT2003','out','2026-01-16','Jubin BMS(1990) Sdn Bhd','Project Expense','PJ1057','Hong Leong Bank','27400002618',64.8,64.8,0,'QT3184424','Tiles Supplies','','2026-01-21',[sp('PJ1057',64.8,'Item Supplies','Tiles Supplies')]), mk('AT2004','out','2026-01-16','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1062','OCBC Bank','7161154406',16800,8400,0,'INV2601/0017','','','2026-01-29',[sp('PJ1062',8400,'Painting Work','')]), mk('AT2005','out','2026-01-16','VIP LIGHTING & SERVICES','Project Expense','PJ1063','Maybank','551285079989',880,880,0,'INV-01142','Wall Light and Socket','','2026-01-21',[sp('PJ1063',880,'Item Supplies','Wall Light and Socket')]), mk('AT2006','out','2026-01-16','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1067','Hong Leong Bank','19701001505',1264,1264,0,'20260002','','','2026-01-21',[sp('PJ1067',1264,'M/E Work','')]), mk('AT2007','out','2026-01-16','STONETOP RENOVATION','Project Expense','PJ1067','Hong Leong Bank','18100109205',6655,6655,0,'IN2025-719','','','2026-02-05',[sp('PJ1067',6655,'Table Top','')]), mk('AT2008','out','2026-01-16','VIP LIGHTING & SERVICES','Project Expense','PJ1074','Maybank','551285079989',352,352,0,'INV-01143','Light Supplies','','2026-01-21',[sp('PJ1074',352,'Item Supplies','Light Supplies')]), mk('AT2009','out','2026-01-16','ECO LIGHT ELECTRICAL','Project Expense','PJ1075','Public Bank','3233890410',350,350,0,'IV-26010005','','','2026-01-21',[sp('PJ1075',350,'M/E Work','')]), mk('AT2010','out','2026-01-19','THE BEST OFFICE SOLUTIONS SDN BHD','Office Expense','','Public Bank','3206535301',236.2,236.2,0,'TB2601119','Copier Machine','','2026-01-21',[sp('',236.2,'Copier Machine','')]), mk('AT2011','out','2026-01-19','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1069','Hong Leong Bank','19701001505',27587,8276.1,0,'20250032','','','2026-02-05',[sp('PJ1069',8276.1,'M/E Work','')]), mk('AT2012','out','2026-01-19','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1069','Hong Leong Bank','19701001505',7330,2199,0,'20250033','','','2026-02-05',[sp('PJ1069',2199,'A/C Work','')]), mk('AT2013','out','2026-01-20','Brightstone Marketing SDN. BHD.','Office Expense','','Public Bank','3817484711',270,270,0,'CNY-26-052','Chinese New Year Gift','','2026-01-21',[sp('',270,'Gift','Chinese New Year Gift')]), mk('AT2014','out','2026-01-21','Goh Koon Tee','Project Expense','PJ1063','Public Bank','4235782406',120,120,0,'No11410','','','2026-01-22',[sp('PJ1063',120,'Door & Door Frame','')]), mk('AT2015','out','2026-01-21','SIN SOON HUP FURNITURE SDN BHD','Project Expense','PJ1063','Public Bank','3176403511',2800,2800,0,'CS2601-0003','','','2026-01-28',[sp('PJ1063',2800,'Door & Door Frame','')]), mk('AT2016','out','2026-01-21','CHEN ZAKKA AND RENOVATION WORKS','Project Expense','PJ1063','Public Bank','3816592000',450,450,0,'INV2601-07','','','2026-01-21',[sp('PJ1063',450,'Tiles Work','')]), mk('AT2017','out','2026-01-21','LIM QIAN WEN','Office Expense','','Public Bank','6330861511',5033.25,5033.25,0,'','Company Trip Airbnb','Entertainment Fee','2026-01-21',[sp('',5033.25,'Entertainment','Company Trip Airbnb')]), mk('AT2018','out','2026-01-23','AUNTIE ZENNY ENTERPRISE','Project Expense','PJ1067','Maybank','551258519962',675,675,0,'INV/AZ/202601-00011','Cleaning','','2026-01-23',[sp('PJ1067',675,'Miscellaneous','Cleaning')]), mk('AT2019','out','2026-01-23','JAWS WOO ELECTRICAL','Project Expense','PJ1077','Hong Leong Bank','12300280748',16435,8217.5,0,'22/01/2026','','','2026-01-23',[sp('PJ1077',8217.5,'M/E Work','')]), mk('AT2020','out','2026-01-27','Reenex Curtain & Wallpaper Sdn Bhd','Project Expense','PJ1063','Maybank','501217670196',20500,20500,0,'QT-00914','','','2026-02-05',[sp('PJ1063',20500,'Curtain & Blinds','')]), mk('AT2021','out','2026-01-27','GITALY SDN BHD','Project Expense','PJ1063','Hong Leong Bank','2300243462',1200,360,0,'V1633','','','2026-02-04',[sp('PJ1063',360,'Painting Work','')]), mk('AT2022','out','2026-01-27','IDEALS WOODS PROJECT','Project Expense','PJ1063','AmBank','8881049913367',9000,4500,0,'251204-002','','','2026-02-05',[sp('PJ1063',4500,'Carpentry Work','')]), mk('AT2023','out','2026-01-27','Jason Tham Man Hou (Funky Entertainment & Services)','Project Expense','PJ1063','Maybank','101218302423',960,960,0,'H26012617','Cleaning','','2026-02-05',[sp('PJ1063',960,'Miscellaneous','Cleaning')]), mk('AT2024','out','2026-01-27','BH 93 Enterprise','Project Expense','PJ1063','Hong Leong Bank','13900111821',750,750,0,'I12003652','Rorobin','','2026-02-05',[sp('PJ1063',750,'Miscellaneous','Rorobin')]), mk('AT2025','out','2026-01-27','BH 93 Enterprise','Project Expense','PJ1070','Hong Leong Bank','13900111821',500,500,0,'I12003652','Rorobin','','2026-02-05',[sp('PJ1070',500,'Miscellaneous','Rorobin')]), mk('AT2026','out','2026-01-27','WH WOOD SPECIALIST INTERIOR','Project Expense','PJ1070','Hong Leong Bank','21900041577',2755,2755,0,'I12003652','Rorobin','','2026-02-05',[sp('PJ1070',2755,'Miscellaneous','Rorobin')]), mk('AT2027','out','2026-01-28','TNB','Office Expense','','JomPAY','5454',423.3,423.3,0,'1579544237','Electricity Bill','Account No 210330646604','2026-02-05',[sp('',423.3,'Utility','Electricity Bill')]), mk('AT2028','out','2026-01-28','RANHILL SAJ','Office Expense','','JomPAY','3673',41.5,41.5,0,'J26011','Water Bill','Account No 85952418J8250064SAJ','2026-02-05',[sp('',41.5,'Utility','Water Bill')]), mk('AT2029','out','2026-01-28','DDS ALUDNA SDN BHD','Project Expense','PJ1074','Hong Leong Bank','36500069428',2500,2500,0,'Inv2601-016','','','2026-02-05',[sp('PJ1074',2500,'Aluminium Work','')]), mk('AT2030','out','2026-01-28','CC BEST CLEANING SERVICE','Office Expense','','Public Bank','3243345324',220,220,0,'C0807','Cleaning','','2026-02-05',[sp('',220,'Miscellaneous','Cleaning')]), mk('AT2031','out','2026-01-28','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1074','OCBC Bank','7161154406',4685,4695,0,'QUO2601/0045','','','2026-02-05',[sp('PJ1074',4695,'Painting Work','')]), mk('AT2032','out','2026-01-28','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1049','OCBC Bank','7161154406',2800,2800,0,'QUO2601/0046','','','2026-02-05',[sp('PJ1049',2800,'Painting Work','')]), mk('AT2033','out','2026-01-28','TGS FURNISHINGS SDN BHD','Project Expense','PJ1063','Public Bank','3206559401',32644.15,16322.08,0,'QU251003B140','Furniture','','2026-01-29',[sp('PJ1063',16322.08,'Item Supplies','Furniture')]), mk('AT2034','out','2026-01-28','TGS FURNISHINGS SDN BHD','Project Expense','PJ1063','Public Bank','3206559401',14511.2,7255.6,0,'QU250923B077','Sofa','','2026-01-29',[sp('PJ1063',7255.6,'Item Supplies','Sofa')]), mk('AT2035','out','2026-01-28','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1078','Hong Leong Bank','26500050262',32500,10000,0,'QT-000162','','','2026-02-07',[sp('PJ1078',10000,'Masonry Work','')]), mk('AT2036','out','2026-01-28','DOUBLE MAN DESIGN','Project Expense','PJ1069','Alliance Bank','11030018199247',214472,50000,0,'george/1001','','','2026-02-13',[sp('PJ1069',50000,'Masonry Work','')]), mk('AT2037','out','2026-01-28','DENSON SMART TECHNOLOGY SDN. BHD.','Project Expense','PJ1063','UOB Bank','2123018682',598,598,0,'SO-2601/032','Smart Door Lock','','2026-02-05',[sp('PJ1063',598,'Item Supplies','Smart Door Lock')]), mk('AT2038','out','2026-01-28','TGS FURNISHINGS SDN BHD','Project Expense','PJ1063','Public Bank','3206559401',11021.2,5510.6,0,'DU 02674','Dining Pendant and Rug','','2026-02-05',[sp('PJ1063',5510.6,'Item Supplies','Dining Pendant and Rug')]), mk('AT2039','out','2026-01-30','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1059','OCBC Bank','7161154406',5200,5200,0,'QUO2601/0025','','','2026-02-05',[sp('PJ1059',5200,'Painting Work','')]), mk('AT2040','out','2026-01-30','ALUMAESTRO SDN BHD','Project Expense','PJ1063','Public Bank','3232872233',11300,5950,0,'No.1926','','','2026-02-05',[sp('PJ1063',5950,'Autogate','')]), mk('AT2041','out','2026-01-30','TM SANITARY SDN. BHD.','Project Expense','PJ1063','Hong Leong Bank','900202214',300,300,0,'IV-302804','Sanitary Ware','','2026-02-05',[sp('PJ1063',300,'Item Supplies','Sanitary Ware')]), mk('AT2042','out','2026-01-30','ACTS ID HARDWARE SDN. BHD.','Project Expense','PJ1063','Public Bank','3242199401',82,82,0,'HC-002204','Sliding Door Handle','','2026-02-05',[sp('PJ1063',82,'Carpentry Work','Sliding Door Handle')]), mk('AT2043','out','2026-01-30','DDS ALUDNA SDN BHD','Project Expense','PJ1067','Hong Leong Bank','36500069428',3880,3880,0,'INV2512-016','','','2026-02-05',[sp('PJ1067',3880,'Aluminium Work','')]), mk('AT2044','out','2026-01-30','DDS ALUDNA SDN BHD','Project Expense','PJ1067','Hong Leong Bank','36500069428',180,180,0,'INV2601-012','','','2026-02-05',[sp('PJ1067',180,'Aluminium Work','')]), mk('AT2045','out','2026-01-30','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1067','OCBC Bank','7161154406',8470,8470,0,'INV2601/0027','','','2026-02-13',[sp('PJ1067',8470,'Painting Work','')]), mk('AT2046','out','2026-01-30','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1067','OCBC Bank','7161154406',1600,1600,0,'QUO2601/0026','','','2026-02-13',[sp('PJ1067',1600,'Painting Work','')]), mk('AT2047','out','2026-01-30','DDS ALUDNA SDN BHD','Project Expense','PJ1063','Hong Leong Bank','36500069428',60395,20550,0,'INV2510-028/INV2602-012','','','2026-02-13',[sp('PJ1063',20550,'Aluminium Work','')]), mk('AT2048','out','2026-01-31','DDS ALUDNA SDN BHD','Project Expense','PJ1059','Hong Leong Bank','36500069428',20550,10550,0,'INV2601-028','','','2026-02-04',[sp('PJ1059',10550,'Aluminium Work','')]), mk('AT2049','out','2026-01-31','HANER EAN PROTECT SDN BHD','Project Expense','PJ1079','Public Bank','3241211328',372,372,0,'IV-01125','Floorgard','','2026-02-03',[sp('PJ1079',372,'Miscellaneous','Floorgard')]), mk('AT2050','out','2026-01-31','LIEW WEI SOON','Project Expense','PJ1061','Public Bank','5379920173386100',489.55,489.55,0,'','Taobao Furniture','','2026-02-02',[sp('PJ1061',489.55,'Item Supplies','Taobao Furniture')]), mk('AT2051','out','2026-01-31','LIEW WEI SOON','Project Expense','PJ1071','Public Bank','5379920173386100',405.04,405.04,0,'','Taobao Furniture','','2026-02-02',[sp('PJ1071',405.04,'Item Supplies','Taobao Furniture')]), mk('AT2052','out','2026-01-31','LIEW WEI SOON','Office Expense','','Public Bank','5379920173386100',66,66,0,'','Water Dispenser','Monthly Subscription','2026-02-02',[sp('',66,'Utility','Water Dispenser Monthly Subscription')]), mk('AT2053','out','2026-01-31','LIEW WEI SOON','Office Expense','','Public Bank','5379920173386100',226.8,226.8,0,'','Google Workspace','Monthly Subscription','2026-02-02',[sp('',226.8,'Subscription','Google Workspace Monthly Subscription')]), mk('AT2054','out','2026-01-31','LIEW WEI SOON','Office Expense','','Public Bank','5379920173386100',6067,6067,0,'','New Year Gift & Christmas Gift','Gift','2026-02-02',[sp('',6067,'Gift','New Year Gift & Christmas Gift')]), mk('AT2055','out','2026-01-31','LIEW WEI SOON','Office Expense','','Public Bank','5379920173386100',1567.25,1567.25,0,'','Christmas Event','Entertainment','2026-02-02',[sp('',1567.25,'Entertainment','Christmas Event')]), mk('AT2056','in','2026-01-17','','Design Income','PJ1084','','',0,0,6800,'','','','',[sp('PJ1084',6800,'Design Income','')]), mk('AT2057','in','2026-01-19','','Design Income','PJ1085','','',0,0,4750,'','','','',[sp('PJ1085',4750,'Design Income','')]), mk('AT2058','in','2026-01-22','','Design Income','PJ1074','','',0,0,500,'','','','',[sp('PJ1074',500,'Design Income','')]), mk('AT2059','in','2025-12-26','','Government Grant','','','',0,0,1500,'','','Government Training Incentive programme (TIP) Grant','',[]), mk('AT2060','in','2026-01-29','','Construction Income','PJ1070','','',0,0,21690,'','','','',[sp('PJ1070',21690,'Construction Income','')]), mk('AT2061','in','2026-01-29','','Construction Income','PJ1067','','',0,0,37150,'','','','',[sp('PJ1067',37150,'Construction Income','')]), mk('AT2062','in','2026-01-30','','Construction Income','PJ1049','','',0,0,3921,'','','VO','',[sp('PJ1049',3921,'Construction Income','VO')]), mk('AT2063','in','2026-01-31','','Design Income','PJ1079','','',0,0,2550,'','','','',[sp('PJ1079',2550,'Design Income','')]), mk('AT2064','in','2026-01-30','','Government Grant','','','',0,0,300,'','','Government Training Incentive programme (TIP) Grant','',[]), mk('AT2065','in','2026-01-30','','Government Grant','','','',0,0,200,'','','Government Training Incentive programme (TIP) Grant','',[]), ]; const existIds=new Set(ACC_TXNS.map(t=>t.id)); const fresh=rows.filter(r=>!existIds.has(r.id)); if(fresh.length){ACC_TXNS.push(...fresh);saveAccTxns();} localStorage.setItem('inzii_seeded_jan2026','1'); })(); // โ”€โ”€ Seed Feb 2026 transactions (one-time) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function seedFeb2026(){ if(localStorage.getItem('inzii_seeded_feb2026'))return; function mk(id,type,date,payee,cat,proj,bank,acc,total,sub,recv,bill,wd,rem,approved){ return{id,type,submittedDate:date,receivedDate:type==='in'?date:'',payeeName:payee||'',category:cat,projectCode:proj||'',bankName:bank||'',bankAccount:acc||'',totalAmount:total||0,submittedAmount:sub||0,amountReceived:recv||0,billNo:bill||'',workDescription:wd||'',remarks:rem||'',subCategories:[],approvedDate:approved||'',projectSplits:[]}; } const rows=[ mk('AT2066','out','2026-02-01','LEE JING WEN','Project Expense','PJ1059','PUBLIC BANK BHD','6803148521',555.85,555.85,0,'','Item Supplies - Carpentry Use','','2026-02-02'), mk('AT2067','out','2026-02-01','LEE JING WEN','Project Expense','PJ1067','PUBLIC BANK BHD','6803148521',31.38,31.38,0,'','Others - Paint Testing','','2026-02-02'), mk('AT2068','out','2026-02-01','WONG KHANG CHENG','Project Expense','PJ1069','MAYBANK BERHAD','151294911403',26.20,26.20,0,'','Others - Ventilation Block Sample','','2026-02-02'), mk('AT2069','out','2026-02-01','LIM QIAN WEN','Project Expense','PJ1076','PUBLIC BANK BHD','6330861511',12.95,12.95,0,'','Photoshooting','','2026-02-02'), mk('AT2070','out','2026-02-01','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','6330861511',187.78,187.78,0,'','Groceries','','2026-02-02'), mk('AT2071','out','2026-02-01','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','6330861511',50.00,50.00,0,'','Medical Claim','','2026-02-02'), mk('AT2072','out','2026-02-01','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','6330861511',68.09,68.09,0,'','License Fee','','2026-02-02'), mk('AT2073','out','2026-02-01','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','6330861511',180.07,180.07,0,'','Site Use','','2026-02-02'), mk('AT2074','out','2026-02-01','CHONG WEE SHENG','Project Expense','PJ1062','MAYBANK BERHAD','151044390994',27.70,27.70,0,'','Others','','2026-02-02'), mk('AT2075','out','2026-02-01','LIM HONG MIN','Project Expense','PJ1063','PUBLIC BANK BHD','5008984729',277.60,277.60,0,'','Item Supplies','','2026-02-02'), mk('AT2076','out','2026-02-01','TAN JING TING','Office Expense','','Standard Chartered','668194628211',50.00,50.00,0,'','Medical Claim','','2026-02-02'), mk('AT2077','out','2026-02-01','CHAN WAN TENG','Project Expense','PJ1079','MAYBANK BERHAD','114245274403',304.03,304.03,0,'','Item Supplies - Mapei Grouting','','2026-02-02'), mk('AT2078','out','2026-02-01','JANE YAP XING YI','Project Expense','PJ1079','MAYBANK BERHAD','101218333436',21.80,21.80,0,'','Others - Duplicate Key & Site Protection','','2026-02-02'), mk('AT2079','out','2026-02-03','PRO CLEANING ENTERPRISE','Project Expense','PJ1063','PUBLIC BANK BHD','3242940624',1600.00,1600.00,0,'20262020004/20262020005','Miscellaneous - Cleaning','','2026-02-05'), mk('AT2080','out','2026-02-03','JASON THAM MAN HOU (FUNKY ENTERTAINMENT & SERVICES)','Project Expense','PJ1063','MAYBANK BERHAD','101218302423',720.00,720.00,0,'H26020216','Miscellaneous - Cleaning','','2026-02-05'), mk('AT2081','out','2026-02-03','AT WOOD FURNITURE','Project Expense','PJ1067','PUBLIC BANK BHD','3212349003',44000.00,26400.00,0,'ATW/INV/2510-002','Carpentry Work','','2026-02-05'), mk('AT2082','out','2026-02-03','AUNTIE ZENNY ENTERPRISE','Project Expense','PJ1067','MAYBANK BERHAD','551258519962',250.00,250.00,0,'NV/AZ/202601-00065','Miscellaneous - Cleaning','','2026-02-03'), mk('AT2083','out','2026-02-03','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1067','HONG LEONG BANK BHD','12300285671',11672.80,1167.28,0,'No1659','Ceiling Work','','2026-02-05'), mk('AT2084','out','2026-02-03','CHEE HUI STAINLESS STEEL','Project Expense','PJ1070','PUBLIC BANK BHD','3181948234',2750.00,2750.00,0,'1329','Metal Work','','2026-02-05'), mk('AT2085','out','2026-02-03','PRO CLEANING ENTERPRISE','Project Expense','PJ1070','PUBLIC BANK BHD','3242940624',305.00,305.00,0,'20262020002/20262020003','Miscellaneous - Cleaning','','2026-02-05'), mk('AT2086','in','2026-02-03','','Construction Income','PJ1074','','',0,0,31404.00,'','','20/1-10000; 22/1-1404; 27/1-10000; 3/2-10000',''), mk('AT2087','in','2026-02-05','','Design Income','PJ1062','','',0,0,5000.00,'','','',''), mk('AT2088','in','2026-02-07','','Construction Income','PJ1079','','',0,0,52000.00,'','','6/2-32000; 7/2-20000',''), mk('AT2089','in','2026-02-13','','Construction Income','PJ1062','','',0,0,109000.00,'','','',''), mk('AT2090','in','2026-02-13','','Construction Income','PJ1063','','',0,0,385000.00,'','','',''), mk('AT2091','out','2026-02-04','CHONG WEE SHENG','Project Expense','PJ1062','MAYBANK BERHAD','151044390994',40.00,40.00,0,'','Others','','2026-02-05'), mk('AT2092','out','2026-02-04','BEST LIGHT CITY SDN BHD','Project Expense','PJ1063','PUBLIC BANK BHD','3204748708',158.00,158.00,0,'T03_SO006157','Item Supplies - Exhaust Fan Supply','','2026-02-04'), mk('AT2093','out','2026-02-05','STONETOP RENOVATION','Project Expense','PJ1059','HONG LEONG BANK BHD','18100109205',1854.00,1854.00,0,'26/01/2013','Table Top','','2026-02-05'), mk('AT2094','out','2026-02-05','REMARKABLES STRATEGY PLT','Office Expense','','Alliance Bank Berhad','11210013031698',1000.00,1000.00,0,'I-000137','Accounting Fee','','2026-02-07'), mk('AT2095','out','2026-02-05','PFS & PARTNERS PLT','Office Expense','','Alliance Bank Berhad','11670010037600',2371.68,2371.68,0,'24/PFS/430/25/PFS/152/25/PFS/509','Tax Agent Fee','','2026-02-07'), mk('AT2096','out','2026-02-05','BRILLIANT CLEANING MANAGEMENT AND SERVICES SDN BHD','Office Expense','','HONG LEONG BANK BHD','18100174632',120.00,120.00,0,'INV26020023','Miscellaneous - Cleaning','','2026-02-05'), mk('AT2097','out','2026-02-05','H GALLERY SDN BHD','Project Expense','PJ1058','OUB','1333049797',1000.00,1000.00,0,'NVC00121','Photoshooting','','2026-02-13'), mk('AT2098','out','2026-02-05','H GALLERY SDN BHD','Project Expense','PJ1061','OUB','1333049797',1000.00,1000.00,0,'NVC00121','Photoshooting','','2026-02-13'), mk('AT2099','out','2026-02-05','H GALLERY SDN BHD','Project Expense','PJ1076','OUB','1333049797',700.00,700.00,0,'NVC00121','Photoshooting','','2026-02-13'), mk('AT2100','out','2026-02-05','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1063','HONG LEONG BANK','26500050262',6000.00,6000.00,0,'I-202601-025','Masonry Work','','2026-02-13'), mk('AT2101','out','2026-02-05','ECO PRO CLEANING SERVICE','Project Expense','PJ1063','HONG LEONG BANK','19700142458',230.00,230.00,0,'No : 631','Miscellaneous - Cleaning','','2026-02-05'), mk('AT2102','out','2026-02-05','SHIEN FENG RENOVATION ENTERPRISE','Project Expense','PJ1062','HONG LEONG BANK BHD','900132748',24730.00,24730.00,0,'INV NO- 20250240','Tile Work','','2026-02-13'), mk('AT2103','out','2026-02-05','GITALY SDN BHD','Project Expense','PJ1063','HONG LEONG BANK BHD','2300243462',7225.00,7225.00,0,'INV-2602-0006','Painting Work','','2026-02-13'), mk('AT2104','out','2026-02-05','MEGAPIPE ENTERPRISE','Project Expense','PJ1067','United Overseas Bank (UOB)','9113050183',300.00,300.00,0,'# 4109','Plumbing Work','','2026-02-05'), mk('AT2105','out','2026-02-05','STONETOP RENOVATION','Project Expense','PJ1059','HONG LEONG BANK BHD','18100109205',11961.00,11961.00,0,'IN2025-431','Table Top','','2026-02-05'), mk('AT2106','out','2026-02-05','AT WOOD FURNITURE','Project Expense','PJ1059','PUBLIC BANK BHD','3212349003',93510.00,9351.00,0,'ATW/INV/2506-001','Carpentry Work','',''), mk('AT2107','out','2026-02-05','AT WOOD FURNITURE','Project Expense','PJ1063','PUBLIC BANK BHD','3212349003',249194.00,25000.00,0,'ATW/INV/2510-001','Carpentry Work','','2026-02-05'), mk('AT2108','out','2026-02-07','GITALY SDN BHD','Project Expense','PJ1059','HONG LEONG BANK BHD','2300243462',25184.00,7555.20,0,'V1579','Painting Work','','2026-02-13'), mk('AT2109','out','2026-02-07','VIP LIGHTING & SERVICES','Project Expense','PJ1074','MAYBANK BERHAD','551285079989',285.00,285.00,0,'INV-01178','Item Supplies - Light Supply','','2026-02-11'), mk('AT2110','out','2026-02-07','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1079','HONG LEONG BANK BHD','19701001505',9466.00,7572.80,0,'20260004','M/E Work','','2026-02-13'), mk('AT2111','out','2026-02-07','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1079','HONG LEONG BANK','26500050262',8130.00,5000.00,0,'QT-000001','Masonry Work','','2026-02-13'), mk('AT2112','out','2026-02-08','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Office Expense','','','',2333.00,2333.00,0,'CP204','Income Tax','','2026-02-09'), mk('AT2113','out','2026-02-08','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Office Expense','','','',1678.55,1678.55,0,'PCB','Salary PCB','','2026-02-09'), mk('AT2114','out','2026-02-08','HRDCORP','Office Expense','','JOMPAY','500181',422.55,422.55,0,'LEVY','HRD Levy','','2026-02-09'), mk('AT2115','out','2026-02-08','KUMPULAN WANG SIMPANAN PEKERJA','Office Expense','','','',11780.00,11780.00,0,'KWSP','EPF Payment','','2026-02-09'), mk('AT2116','out','2026-02-08','PERTUBUHAN KESELAMATAN SOSIAL','Office Expense','','','',1182.00,1182.00,0,'SOCSO & EIS','SOCSO & EIS Payment','','2026-02-09'), mk('AT2117','out','2026-02-09','TM SANITARY SDN. BHD.','Project Expense','PJ1063','HONG LEONG BANK BHD','900202214',240.00,240.00,0,'IV-302811','Item Supplies','','2026-02-11'), mk('AT2118','out','2026-02-09','WANG POT SHIN','Project Expense','PJ1063','HONG LEONG BANK BHD','37950070372',600.00,600.00,0,'INV00030','Others','','2026-02-11'), mk('AT2119','out','2026-02-09','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1074','HONG LEONG BANK','26500050262',550.00,550.00,0,'QT-000158 / I-202512-024','Masonry Work','','2026-02-13'), mk('AT2120','out','2026-02-09','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1074','OCBC BANK','7161154406',4695.00,4695.00,0,'QUO2601/0045','Painting Work','','2026-02-13'), mk('AT2121','out','2026-02-09','KIM YAP ENGINEERING SDN BHD','Project Expense','PJ1074','PUBLIC BANK BHD','3236679205',24500.00,24500.00,0,'IV0226-03','Awning Work','',''), mk('AT2122','out','2026-02-09','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1074','HONG LEONG BANK','26500050262',450.00,450.00,0,'I-202601-016','Masonry Work','','2026-02-13'), mk('AT2123','out','2026-02-11','VIP LIGHTING & SERVICES','Project Expense','PJ1063','MAYBANK BERHAD','551285079989',386.00,386.00,0,'INV-01173','Item Supplies','','2026-02-13'), mk('AT2124','out','2026-02-11','YONG CHEU CHAI (YAU PLUMBING)','Project Expense','PJ1063','HONG LEONG BANK BHD','32350007593',11950.00,11950.00,0,'No.3198','Plumbing Work','','2026-02-13'), mk('AT2125','out','2026-02-11','CHEN ZAKKA AND RENOVATION WORKS','Project Expense','PJ1063','PUBLIC BANK BHD','3816592000',600.00,600.00,0,'INV2602-09','Flooring Work','','2026-02-13'), mk('AT2126','out','2026-02-11','MEGAPIPE ENTERPRISE','Project Expense','PJ1067','United Overseas Bank (UOB)','9113050183',300.00,300.00,0,'# 4109','Plumbing Work','','2026-02-13'), mk('AT2127','out','2026-02-11','JASON THAM MAN HOU (FUNKY ENTERTAINMENT & SERVICES)','Project Expense','PJ1074','MAYBANK BERHAD','101218302423',450.00,450.00,0,'H2602098','Miscellaneous - Cleaning','','2026-02-13'), mk('AT2128','out','2026-02-11','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1074','HONG LEONG BANK BHD','19701001505',1382.20,1382.20,0,'20260005','M/E Work','','2026-02-13'), mk('AT2129','out','2026-02-11','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1079','HONG LEONG BANK BHD','12300285671',7906.30,6325.04,0,'No.1747','Ceiling Work','','2026-02-13'), mk('AT2130','out','2026-02-12','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1063','HONG LEONG BANK BHD','19701001505',8034.00,8034.00,0,'20260001','M/E Work','','2026-02-13'), mk('AT2131','out','2026-02-12','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1063','OCBC BANK','7161154406',12840.00,12840.00,0,'INV2602/0044','Painting Work','','2026-02-13'), mk('AT2132','out','2026-02-12','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1063','OCBC BANK','7161154406',1890.00,1890.00,0,'INV2602/0043','Painting Work','','2026-02-13'), mk('AT2133','out','2026-02-12','BH 93 ENTERPRISE','Project Expense','PJ1062','HONG LEONG BANK BHD','13900111821',250.00,250.00,0,'No.I2003785','Miscellaneous - Rorobin','','2026-02-13'), mk('AT2134','out','2026-02-12','BH 93 ENTERPRISE','Project Expense','PJ1063','HONG LEONG BANK BHD','13900111821',1000.00,1000.00,0,'No.I2003785','Miscellaneous - Rorobin','','2026-02-13'), mk('AT2135','out','2026-02-13','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1074','HONG LEONG BANK','26500050262',1000.00,1000.00,0,'QT-000158 / I-202512-024','Masonry Work','',''), mk('AT2136','out','2026-02-13','AT WOOD FURNITURE','Project Expense','PJ1059','PUBLIC BANK BHD','3212349003',2500.00,2500.00,0,'ATW/INV/2602-002','Carpentry Work','','2026-03-16'), mk('AT2137','out','2026-02-13','JASON THAM MAN HOU (FUNKY ENTERTAINMENT & SERVICES)','Project Expense','PJ1062','MAYBANK BERHAD','101218302423',880.00,880.00,0,'H26021211','Miscellaneous - Cleaning','','2026-02-13'), mk('AT2138','out','2026-02-13','JASON THAM MAN HOU (FUNKY ENTERTAINMENT & SERVICES)','Project Expense','PJ1063','MAYBANK BERHAD','101218302423',720.00,720.00,0,'H26021210','Miscellaneous - Cleaning','','2026-02-13'), mk('AT2139','out','2026-02-13','AT WOOD FURNITURE','Project Expense','PJ1074','PUBLIC BANK BHD','3212349003',800.00,800.00,0,'ATW/INV/2602-001','Carpentry Work','','2026-02-13'), mk('AT2140','out','2026-02-13','LEE JING WEN','Salary Expense','','PUBLIC BANK BHD','6803148521',1600.00,1600.00,0,'','Incentive','','2026-02-13'), mk('AT2141','out','2026-02-13','WONG KHANG CHENG','Salary Expense','','MAYBANK BERHAD','151294911403',2000.00,2000.00,0,'','Incentive','','2026-02-13'), mk('AT2142','out','2026-02-13','LIM QIAN WEN','Salary Expense','','PUBLIC BANK BHD','6330861511',2000.00,2000.00,0,'','Incentive','','2026-02-13'), mk('AT2143','out','2026-02-13','CHONG WEE SHENG','Salary Expense','','MAYBANK BERHAD','151044390994',2000.00,2000.00,0,'','Incentive','','2026-02-13'), mk('AT2144','out','2026-02-13','LIM HONG MIN','Salary Expense','','PUBLIC BANK BHD','5008984729',1750.00,1750.00,0,'','Incentive','','2026-02-13'), mk('AT2145','out','2026-02-13','TAN JING TING','Salary Expense','','Standard Chartered','668194628211',1300.00,1300.00,0,'','Incentive','','2026-02-13'), mk('AT2146','out','2026-02-13','CHAN WAN TENG','Salary Expense','','MAYBANK BERHAD','114245274403',1600.00,1600.00,0,'','Incentive','','2026-02-13'), mk('AT2147','out','2026-02-13','JANE YAP XING YI','Salary Expense','','MAYBANK BERHAD','101218333436',1600.00,1600.00,0,'','Incentive','','2026-02-13'), mk('AT2148','out','2026-02-13','AT WOOD FURNITURE','Project Expense','PJ1063','PUBLIC BANK BHD','3212349003',249194.00,30000.00,0,'ATW/INV/2510-001','Carpentry Work','','2026-02-13'), mk('AT2149','out','2026-02-14','KRONOTEX TRADING','Project Expense','PJ1063','AFFIN BANK','100360343954',32882.00,8500.00,0,'QT-2506001/I-2512002','Flooring Work - Engineering Wood Floor 2nd Pmt','','2026-02-14'), mk('AT2150','out','2026-02-14','GOH KOON TEE','Project Expense','PJ1063','PUBLIC BANK BHD','4235782406',150.00,150.00,0,'No11411','Door & Door Frame - Modify Door Full Payment','','2026-02-14'), mk('AT2151','out','2026-02-14','DDS ALUDNA SDN BHD','Project Expense','PJ1063','HONG LEONG BANK','36500069428',70490.00,19245.00,0,'INV2510-028/INV2602-012','Aluminium Work - Balance Payment','','2026-02-14'), mk('AT2152','out','2026-02-15','LIEW WEI SOON','Salary Expense','','HONG LEONG BANK BHD','7050209799',5000.00,5000.00,0,'','Incentive','','2026-02-15'), mk('AT2153','out','2026-02-24','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',226.80,226.80,0,'','Google Workspace - Monthly Subscription','','2026-02-24'), mk('AT2154','out','2026-02-24','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',66.00,66.00,0,'','Water Dispenser - Monthly Subscription','','2026-02-24'), mk('AT2155','out','2026-02-24','LIEW WEI SOON','Office Expense','','HONG LEONG BANK BHD','7050209799',1890.00,1890.00,0,'','Meta Ads - Advertising Fee','','2026-02-24'), mk('AT2156','out','2026-02-24','','Office Expense','','','',40.00,40.00,0,'SSM Renewal','Renewal Fee','','2026-02-24'), mk('AT2157','out','2026-02-26','THE BEST OFFICE SOLUTIONS SDN BHD','Office Expense','','PUBLIC BANK BHD','3206535301',209.80,209.80,0,'','Copier Machine - Monthly Subscription','','2026-02-26'), mk('AT2158','out','2026-02-26','TOCOS LIVING (M) SDN BHD','Project Expense','PJ1079','PUBLIC BANK BHD','3227847315',3400.00,2380.00,0,'','Flooring Work','','2026-02-26'), mk('AT2159','out','2026-02-26','AT WOOD FURNITURE','Project Expense','PJ1079','PUBLIC BANK BHD','3212349003',30585.00,15292.50,0,'','Carpentry Work','','2026-02-27'), mk('AT2160','out','2026-02-26','KEE CHAI XUAN','Office Expense','','CIMB Bank','7043595775',6750.00,3375.00,0,'','Rebranding','','2026-02-26'), ]; const existIds=new Set(ACC_TXNS.map(t=>t.id)); const fresh=rows.filter(r=>!existIds.has(r.id)); if(fresh.length){ACC_TXNS.push(...fresh);saveAccTxns();} localStorage.setItem('inzii_seeded_feb2026','1'); })(); // โ”€โ”€ Seed Mar 2026 transactions (one-time) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function seedMar2026(){ if(localStorage.getItem('inzii_seeded_mar2026'))return; function mk(id,type,date,payee,cat,proj,bank,acc,total,sub,recv,bill,wd,rem,approved){ return{id,type,submittedDate:date,receivedDate:type==='in'?date:'',payeeName:payee||'',category:cat,projectCode:proj||'',bankName:bank||'',bankAccount:acc||'',totalAmount:total||0,submittedAmount:sub||0,amountReceived:recv||0,billNo:bill||'',workDescription:wd||'',remarks:rem||'',subCategories:[],approvedDate:approved||'',projectSplits:[]}; } const rows=[ mk('AT2161','out','2026-03-01','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Office Expense','','','',1232.80,1232.80,0,'PCB','Salary PCB','','2026-03-02'), mk('AT2162','out','2026-03-01','HRDCORP','Office Expense','','JOMPAY','500181',394.00,394.00,0,'Levy','HRD Levy','','2026-03-02'), mk('AT2163','out','2026-03-01','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Office Expense','','','',2333.00,2333.00,0,'CP204','Income Tax','','2026-03-02'), mk('AT2164','out','2026-03-01','TNB','Office Expense','','JOMPAY','5454',397.90,397.90,0,'Account No. 210330646604','TNB Electricity Bill','','2026-03-02'), mk('AT2165','out','2026-03-01','RANHILL SAJ','Office Expense','','JOMPAY','3673',41.50,41.50,0,'Account No.85952418J8250064','SAJ Water Bill','','2026-03-02'), mk('AT2166','out','2026-03-02','LIEW WEI SOON','Office Expense','','HONG LEONG BANK BHD','7050209799',1237.80,1237.80,0,'','CNY Dinner - Entertainment','','2026-03-04'), mk('AT2167','out','2026-03-02','LEE JING WEN','Project Expense','PJ1074','PUBLIC BANK BHD','6803148521',663.10,663.10,0,'','Item Supplies - Pebble Stone','','2026-03-04'), mk('AT2168','out','2026-03-02','WONG KHANG CHENG','Project Expense','PJ1077','MAYBANK BERHAD','151294911403',145.20,145.20,0,'','Others - Client Treat','','2026-03-04'), mk('AT2169','out','2026-03-02','WONG KHANG CHENG','Project Expense','PJ1071','MAYBANK BERHAD','151294911403',107.30,107.30,0,'','Photoshooting','','2026-03-04'), mk('AT2170','out','2026-03-02','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',50.00,50.00,0,'','Medical Claim','','2026-03-04'), mk('AT2171','out','2026-03-02','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',35.32,35.32,0,'','Groceries - Office Door Bell','','2026-03-04'), mk('AT2172','out','2026-03-02','LIM QIAN WEN','Office Expense','','MAYBANK BERHAD','101142059148',156.85,156.85,0,'','Entertainment - Team Bonding','','2026-03-04'), mk('AT2173','out','2026-03-02','LIM QIAN WEN','Office Expense','','MAYBANK BERHAD','101142059148',13.90,13.90,0,'','License Fee - PDF License','','2026-03-04'), mk('AT2174','out','2026-03-02','CHONG WEE SHENG','Project Expense','PJ1070','MAYBANK BERHAD','151044390994',142.40,142.40,0,'','Photoshooting','','2026-03-04'), mk('AT2175','out','2026-03-02','CHONG WEE SHENG','Project Expense','PJ1083','MAYBANK BERHAD','151044390994',380.76,380.76,0,'','Site Visit','','2026-03-04'), mk('AT2176','out','2026-03-02','LIM HONG MIN','Project Expense','PJ1063','PUBLIC BANK BHD','5008984729',34.50,34.50,0,'','Painting Work','','2026-03-04'), mk('AT2177','out','2026-03-02','LIM HONG MIN','Project Expense','PJ1067','PUBLIC BANK BHD','5008984729',1.30,1.30,0,'','Others - Sand Paper','','2026-03-04'), mk('AT2178','out','2026-03-02','LIM HONG MIN','Office Expense','','PUBLIC BANK BHD','5008984729',50.00,50.00,0,'','Medical Claim','','2026-03-04'), mk('AT2179','out','2026-03-02','JANE YAP XING YI','Project Expense','PJ1074','MAYBANK BERHAD','101218333436',11.50,11.50,0,'','Others - Shipping Fee','','2026-03-04'), mk('AT2180','out','2026-03-02','JANE YAP XING YI','Project Expense','PJ1079','MAYBANK BERHAD','101218333436',13.70,13.70,0,'','Others - Door Stopper','','2026-03-04'), mk('AT2181','out','2026-03-02','JANE YAP XING YI','Office Expense','','MAYBANK BERHAD','101218333436',100.00,100.00,0,'','Medical Claim','','2026-03-04'), mk('AT2182','out','2026-03-02','LIEW WEI SOON','Salary Expense','','HONG LEONG BANK BHD','7050209799',2000.00,2000.00,0,'','Director Withdraw','','2026-03-04'), mk('AT2183','in','2026-03-02','','Payment Refund','PJ1063','','',0,0,105.00,'','Switch Refund','',''), mk('AT2184','in','2026-03-03','','Government Grant','','','',0,0,1700.00,'','Government Training Incentive programme (TIP) Grant','',''), mk('AT2185','in','2026-03-04','','Construction Income','PJ1079','','',0,0,39000.00,'','','',''), mk('AT2186','in','2026-03-10','','Design Income','PJ1086','','',0,0,12000.00,'','','',''), mk('AT2187','in','2026-03-10','','Payment Refund','','','',0,0,350.00,'','New Year Gift Refund (miss delivery)','',''), mk('AT2188','out','2026-03-04','MAHSIN TRANSPORT SDN BHD','Office Expense','','HONG LEONG BANK BHD','12600146829',1080.00,1080.00,0,'','Car Rental - Company Trip Entertainment','','2026-03-04'), mk('AT2189','out','2026-03-04','NW ACADEMY (M) SDN. BHD.','Office Expense','','MAYBANK BERHAD','551276087494',1944.00,1944.00,0,'NWA-Q2603094','Grant Submission - Submission Fee','','2026-03-06'), mk('AT2190','out','2026-03-06','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1078','HONG LEONG BANK BHD','19701001505',20895.00,16716.00,0,'20260003','M/E Work','','2026-03-06'), mk('AT2191','out','2026-03-06','LIM HF CONSTRUCTION','Project Expense','PJ1077','HONG LEONG BANK BHD','12300297360',15229.70,7614.85,0,'QN25-00106/2605/004','Ceiling Work','','2026-03-06'), mk('AT2192','out','2026-03-10','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1078','HONG LEONG BANK','26500050262',32500.00,8000.00,0,'QT-000162','Masonry Work','','2026-03-30'), mk('AT2193','out','2026-03-10','KUMPULAN WANG SIMPANAN PEKERJA','Salary Expense','','','',9923.00,9923.00,0,'KWSP','EPF Payment','','2026-03-12'), mk('AT2194','out','2026-03-10','PERTUBUHAN KESELAMATAN SOSIAL','Salary Expense','','','',979.30,979.30,0,'SOCSO & EIS','SOCSO & EIS Payment','','2026-03-12'), mk('AT2195','out','2026-03-11','FLOORING MASTER ENTERPRISE','Project Expense','PJ1062','PUBLIC BANK BHD','3819644303',19400.00,5820.00,0,'FMQT0126-015','Flooring Work','','2026-03-16'), mk('AT2196','out','2026-03-11','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1079','OCBC Bank','7101373179',230.00,230.00,0,'#260303','Miscellaneous - Cleaning','','2026-03-12'), mk('AT2197','out','2026-03-11','LIEW WEI SOON','Office Expense','','HONG LEONG BANK BHD','7050209799',185.00,185.00,0,'','Entertainment','','2026-03-12'), mk('AT2198','out','2026-03-11','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','101142059148',1151.45,1151.45,0,'','Entertainment','','2026-03-12'), mk('AT2199','out','2026-03-11','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','101142059148',40.00,40.00,0,'','Site Use - Masking Tape','','2026-03-12'), mk('AT2200','out','2026-03-11','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','101142059148',25.75,25.75,0,'','Stationery - Clipboard','','2026-03-12'), mk('AT2201','out','2026-03-11','CHAN WAN TENG','Project Expense','PJ1060','MAYBANK BERHAD','114245274403',57.60,57.60,0,'','Others','','2026-03-12'), mk('AT2202','out','2026-03-11','CHAN WAN TENG','Office Expense','','MAYBANK BERHAD','114245274403',261.00,261.00,0,'','Entertainment','','2026-03-12'), mk('AT2203','out','2026-03-11','CHAN WAN TENG','Office Expense','','MAYBANK BERHAD','114245274403',358.00,358.00,0,'','Software - 3D Software','','2026-03-12'), mk('AT2204','out','2026-03-14','AT WOOD FURNITURE','Project Expense','PJ1063','PUBLIC BANK BHD','3212349003',249194.00,10000.00,0,'ATW/INV/2510-001','Carpentry Work','','2026-03-16'), mk('AT2205','out','2026-03-14','CHWEE HWA NURSERY SDN BHD','Project Expense','PJ1063','Alliance Bank','11300011835060',58843.00,10000.00,0,'I-202602-055','Landscape','','2026-03-17'), mk('AT2206','out','2026-03-14','JAWS WOO ELECTRICAL','Project Expense','PJ1077','HONG LEONG BANK','12300280748',16435.00,5751.00,0,'22/01/2026','M/E Work','','2026-03-16'), mk('AT2207','out','2026-03-14','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1078','HONG LEONG BANK BHD','12300285671',5090.80,5090.80,0,'No 1757','Ceiling Work','','2026-04-02'), mk('AT2208','out','2026-03-19','HANER EAN PROTECT SDN BHD','Project Expense','PJ1062','PUBLIC BANK BHD','3241211328',323.00,323.00,0,'IV-01238','Miscellaneous - Floorgard','','2026-03-19'), mk('AT2209','out','2026-03-20','KIM YAP ENGINEERING SDN BHD','Project Expense','PJ1062','PUBLIC BANK BHD','3236679205',18500.00,18500.00,0,'IV0226-04','Awning Work','','2026-03-21'), mk('AT2210','in','2026-03-19','','Payment Refund','','','',0,0,3290.00,'','Feruni Point Redeem','',''), mk('AT2211','in','2026-03-26','','Construction Income','PJ1079','','',0,0,26000.00,'','','',''), mk('AT2212','in','2026-03-27','','Construction Income','PJ1077','','',0,0,77400.00,'','','',''), mk('AT2213','out','2026-03-25','TNB','Office Expense','','JOMPAY','5454',448.60,448.60,0,'721622715','TNB Electricity Bill - Acct No.210330646604','','2026-03-29'), mk('AT2214','out','2026-03-25','REMARKABLES STRATEGY PLT','Office Expense','','Alliance Bank Berhad','11210013031698',1000.00,1000.00,0,'I-000150','Accounting Fee','','2026-03-29'), mk('AT2215','out','2026-03-25','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1062','HONG LEONG BANK','26500050262',1800.00,1800.00,0,'I-202603-0014','Masonry Work','','2026-03-30'), mk('AT2216','out','2026-03-27','LIM HF CONSTRUCTION','Project Expense','PJ1077','HONG LEONG BANK BHD','12300297360',15229.70,4568.91,0,'QN25-00106 / 2605/004','Ceiling Work','','2026-03-31'), mk('AT2217','out','2026-03-27','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1079','OCBC BANK','7161154406',9570.00,4785.00,0,'INV2603/0083','Painting Work','','2026-03-30'), mk('AT2218','out','2026-03-27','STONETOP RENOVATION','Project Expense','PJ1063','HONG LEONG BANK BHD','18100109205',10976.00,10976.00,0,'26/01/1943','Table Top','','2026-04-17'), mk('AT2219','out','2026-03-27','DDS ALUDNA SDN BHD','Project Expense','PJ1079','HONG LEONG BANK','36500069428',5390.00,2695.00,0,'INV2603-018','Aluminium Work','','2026-03-30'), mk('AT2220','out','2026-03-27','KK & YK PRO PAINTING SDN BHD','Project Expense','PJ1079','UOB Bank','2593008195',8520.00,5964.00,0,'Q2601-025','Masonry Work - Glass Block Work','','2026-03-30'), mk('AT2221','out','2026-03-27','KIM YAP ENGINEERING SDN BHD','Project Expense','PJ1079','PUBLIC BANK BHD','3236679205',6091.75,6091.75,0,'IV0326-09','Stainless Steel Work','','2026-04-17'), mk('AT2222','out','2026-03-28','J SPACEEE TRADING','Project Expense','PJ1063','AFFIN BANK','106600013760',32882.00,7941.00,0,'QT-2506001/I-2512002','Flooring Work','','2026-03-31'), mk('AT2223','out','2026-03-28','AT WOOD FURNITURE','Project Expense','PJ1063','PUBLIC BANK BHD','3212349003',249194.00,10000.00,0,'ATW/INV/2510-001','Carpentry Work','','2026-03-30'), mk('AT2224','out','2026-03-28','TOCOS LIVING (M) SDN BHD','Project Expense','PJ1079','PUBLIC BANK BHD','3227847315',3400.00,1020.00,0,'I26-1308','Flooring Work','','2026-03-29'), mk('AT2225','out','2026-03-30','QUANTITY VILLAGE SDN. BHD.','Project Expense','PJ1063','RHB BANK','21452100035118',480.00,480.00,0,'','Others - Shipping Fee','','2026-03-30'), mk('AT2226','out','2026-03-30','LIEW WEI SOON','Project Expense','PJ1063','PUBLIC BANK BHD','5379920173386100',66.03,66.03,0,'','Item Supplies','','2026-04-02'), mk('AT2227','out','2026-03-30','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',66.00,66.00,0,'','Water Dispenser - Monthly Subscription','','2026-04-02'), mk('AT2228','out','2026-03-30','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',231.03,231.03,0,'','Facebook Ads - Advertising Fee','','2026-04-02'), mk('AT2229','out','2026-03-30','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',226.80,226.80,0,'','Google Workspace - Monthly Subscription','','2026-04-02'), mk('AT2230','out','2026-03-30','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',387.95,387.95,0,'','Entertainment - Company Gathering','','2026-04-02'), mk('AT2231','out','2026-03-30','CC BEST CLEANING SERVICE','Office Expense','','PUBLIC BANK BHD','3243345324',330.00,330.00,0,'C1014','Office Cleaning','','2026-04-02'), mk('AT2232','out','2026-03-30','DDS ALUDNA SDN BHD','Project Expense','PJ1059','HONG LEONG BANK','36500069428',5150.00,4700.00,0,'INV2603-012','Aluminium Work','','2026-04-17'), mk('AT2233','out','2026-03-31','INZII DESIGN STUDIO PLT','Office Expense','','BANK SIMPANAN NASIONAL','112941100030943',5000.00,5000.00,0,'','BSN Loan Payment','','2026-03-31'), ]; const existIds=new Set(ACC_TXNS.map(t=>t.id)); const fresh=rows.filter(r=>!existIds.has(r.id)); if(fresh.length){ACC_TXNS.push(...fresh);saveAccTxns();} localStorage.setItem('inzii_seeded_mar2026','1'); })(); // โ”€โ”€ Seed Apr 2026 transactions (one-time) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function seedApr2026(){ if(localStorage.getItem('inzii_seeded_apr2026'))return; function mk(id,type,date,payee,cat,proj,bank,acc,total,sub,recv,bill,wd,rem,approved){ return{id,type,submittedDate:date,receivedDate:type==='in'?date:'',payeeName:payee||'',category:cat,projectCode:proj||'',bankName:bank||'',bankAccount:acc||'',totalAmount:total||0,submittedAmount:sub||0,amountReceived:recv||0,billNo:bill||'',workDescription:wd||'',remarks:rem||'',subCategories:[],approvedDate:approved||'',projectSplits:[]}; } const rows=[ mk('AT2234','out','2026-04-02','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1077','HONG LEONG BANK','26500050262',4500.00,4500.00,0,'I-202603-0018','Masonry Work','','2026-04-16'), mk('AT2235','out','2026-04-02','SDR (HORIZON) SDN.BHD.','Project Expense','PJ1078','MAYBANK BERHAD','551100851092',3350.00,1675.00,0,'SO-2604-0001','Door & Door Frame','','2026-04-02'), mk('AT2236','out','2026-04-02','WONG KHANG CHENG','Project Expense','PJ1077','MAYBANK BERHAD','151294911403',1032.40,1032.40,0,'','Carpentry Work','','2026-04-02'), mk('AT2237','out','2026-04-02','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',20.40,20.40,0,'','Entertainment - Company Trip Expenses','','2026-04-02'), mk('AT2238','out','2026-04-02','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',69.04,69.04,0,'','Site Use - Measuring Tape','','2026-04-02'), mk('AT2239','out','2026-04-02','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',95.00,95.00,0,'','Software - Software Install','','2026-04-02'), mk('AT2240','out','2026-04-02','LIM QIAN WEN','Office Expense','','MAYBANK BERHAD','101142059148',252.03,252.03,0,'','Groceries','','2026-04-02'), mk('AT2241','out','2026-04-02','CHONG WEE SHENG','Office Expense','','MAYBANK BERHAD','151044390994',373.94,373.94,0,'','Entertainment - Company Trip Expenses','','2026-04-02'), mk('AT2242','out','2026-04-02','LIM HONG MIN','Project Expense','PJ1077','PUBLIC BANK BHD','5008984729',99.50,99.50,0,'','Others - Canvas','','2026-04-02'), mk('AT2243','out','2026-04-02','LIM HONG MIN','Office Expense','','PUBLIC BANK BHD','5008984729',29.00,29.00,0,'','Entertainment - Company Trip Expenses','','2026-04-02'), mk('AT2244','out','2026-04-02','TAN JING TING','Office Expense','','Standard Chartered','668194628211',55.50,55.50,0,'','Entertainment - Company Trip Expenses','','2026-04-02'), mk('AT2245','out','2026-04-02','CHAN WAN TENG','Project Expense','PJ1079','MAYBANK BERHAD','114245274403',39.75,39.75,0,'','Others - Door Stopper, TV Electrical Cover','','2026-04-02'), mk('AT2246','out','2026-04-02','CHAN WAN TENG','Office Expense','','MAYBANK BERHAD','114245274403',40.00,40.00,0,'','Services - PC Services','','2026-04-02'), mk('AT2247','out','2026-04-02','CHAN WAN TENG','Office Expense','','MAYBANK BERHAD','114245274403',18.49,18.49,0,'','Groceries - Door Handle','','2026-04-02'), mk('AT2248','out','2026-04-02','JANE YAP XING YI','Office Expense','','MAYBANK BERHAD','101218333436',513.88,513.88,0,'','Entertainment - Company Trip Expenses','','2026-04-02'), mk('AT2249','out','2026-04-03','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1067','HONG LEONG BANK BHD','19701001505',400.00,400.00,0,'20260007','A/C Work','','2026-04-14'), mk('AT2250','out','2026-04-03','ECOWARE INTERNATIONAL (M) SDN BHD','Project Expense','PJ1071','UOB BANK','2213124716',291.20,291.20,0,'SINJB25110595','Item Supplies - Kitchen Accessories','','2026-04-06'), mk('AT2251','out','2026-04-03','TOCOS LIVING (M) SDN BHD','Project Expense','PJ1078','PUBLIC BANK BHD','3227847315',13420.00,9394.00,0,'I26-1326','Flooring Work','','2026-04-13'), mk('AT2252','out','2026-04-03','FOCUS PIXEL','Project Expense','PJ1086','UOB BANK','9113054499',6550.00,6550.00,0,'IV01016','Outsource Drafter','','2026-04-17'), mk('AT2253','out','2026-04-05','FLOORING MASTER ENTERPRISE','Project Expense','PJ1077','PUBLIC BANK BHD','3819644303',7800.00,3900.00,0,'FMQT2604-011','Flooring Work','','2026-04-06'), mk('AT2254','out','2026-04-05','RANHILL SAJ','Office Expense','','JOMPAY','3673',41.50,41.50,0,'J26031','SAJ Water Bill - Acct No.85952418J8250064','','2026-04-06'), mk('AT2255','out','2026-04-07','KOW HOCK BUILDING MATERIALS (NJ) SDN BHD','Project Expense','PJ1069','PUBLIC BANK BHD','3244044409',2632.50,2632.50,0,'NJSO-00001902','Item Supplies - Ventilation Block Supply','','2026-04-17'), mk('AT2256','out','2026-04-07','MENG JIANG TRADING','Project Expense','PJ1077','Alliance Bank','510780010015680',59040.00,29520.00,0,'QT-000053','Carpentry Work','','2026-04-16'), mk('AT2257','out','2026-04-07','HANER EAN PROTECT SDN BHD','Project Expense','PJ1077','PUBLIC BANK BHD','3241211328',762.00,762.00,0,'IV-01308','Miscellaneous - Floorgard','','2026-04-14'), mk('AT2258','in','2026-04-06','','Government Grant','','','',0,0,1700.00,'','Government Training Incentive programme (TIP) Grant','',''), mk('AT2259','out','2026-04-09','BH 93 ENTERPRISE','Project Expense','PJ1062','HONG LEONG BANK BHD','13900111821',250.00,250.00,0,'I2004101','Miscellaneous - Rorobin','','2026-04-14'), mk('AT2260','out','2026-04-09','BH 93 ENTERPRISE','Project Expense','PJ1063','HONG LEONG BANK BHD','13900111821',250.00,250.00,0,'I2004101','Miscellaneous - Rorobin','','2026-04-14'), mk('AT2261','out','2026-04-09','BH 93 ENTERPRISE','Project Expense','PJ1077','HONG LEONG BANK BHD','13900111821',250.00,250.00,0,'I2004101','Miscellaneous - Rorobin','','2026-04-14'), mk('AT2262','out','2026-04-09','DDS ALUDNA SDN BHD','Project Expense','PJ1078','HONG LEONG BANK','36500069428',11240.00,5620.00,0,'20260408001','Aluminium Work','','2026-04-17'), mk('AT2263','out','2026-04-12','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Office Expense','','','',2333.00,2333.00,0,'CP204','Income Tax','','2026-04-13'), mk('AT2264','out','2026-04-12','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Salary Expense','','','',1767.95,1767.95,0,'PCB','Salary PCB','','2026-04-13'), mk('AT2265','out','2026-04-12','HRDCORP','Office Expense','','','',385.00,385.00,0,'Levy','HRD Levy','','2026-04-13'), mk('AT2266','out','2026-04-12','KUMPULAN WANG SIMPANAN PEKERJA','Salary Expense','','','',11540.00,11540.00,0,'KWSP','EPF Payment','','2026-04-13'), mk('AT2267','out','2026-04-12','PERTUBUHAN KESELAMATAN SOSIAL','Salary Expense','','','',1143.70,1143.70,0,'SOCSO & EIS','SOCSO & EIS Payment','','2026-04-13'), mk('AT2268','out','2026-04-14','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1077','OCBC Bank','7161154406',9500.00,4750.00,0,'QUO2509/0330','Painting Work','','2026-04-17'), mk('AT2269','out','2026-04-15','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1078','HONG LEONG BANK BHD','12300285671',2462.00,2462.00,0,'No 1756','Ceiling Work','','2026-04-16'), mk('AT2270','out','2026-04-15','HANER EAN PROTECT SDN BHD','Project Expense','PJ1078','PUBLIC BANK BHD','3241211328',654.00,654.00,0,'IV-01299','Miscellaneous - Floorgard','','2026-04-16'), mk('AT2271','out','2026-04-16','YI RONG RENOVATION WORKS','Project Expense','PJ1062','MAYBANK','501534162748',610.00,610.00,0,'No11761','Masonry Work','','2026-04-17'), mk('AT2272','out','2026-04-17','DDS ALUDNA SDN BHD','Project Expense','PJ1059','HONG LEONG BANK','36500069428',5150.00,450.00,0,'INV2603-012','Aluminium Work','','2026-04-17'), mk('AT2273','out','2026-04-17','DDS ALUDNA SDN BHD','Project Expense','PJ1063','HONG LEONG BANK','36500069428',1260.00,1260.00,0,'INV2604-001','Aluminium Work - Lattice Design','','2026-04-17'), mk('AT2274','in','2026-04-15','','Design Income','PJ1087','','',0,0,10000.00,'','','',''), mk('AT2275','out','2026-04-17','AT WOOD FURNITURE','Project Expense','PJ1079','PUBLIC BANK BHD','3212349003',30585.00,9175.50,0,'ATW/INV/2602-005','Carpentry Work','','2026-04-17'), mk('AT2276','out','2026-04-17','CHWEE HWA NURSERY SDN BHD','Project Expense','PJ1063','Alliance Bank','11300011835060',58843.00,10000.00,0,'I-202602-055','Landscape','','2026-04-17'), mk('AT2277','out','2026-04-17','KIM YAP ENGINEERING SDN BHD','Project Expense','PJ1063','PUBLIC BANK BHD','3236679205',19788.50,19788.50,0,'IV1125-02 /IV0226-02','Awning Work','','2026-04-30'), mk('AT2278','out','2026-04-17','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1079','OCBC Bank','7101373179',660.00,660.00,0,'#260411','Miscellaneous - Cleaning','','2026-04-17'), mk('AT2279','out','2026-04-18','KOW HOCK BUILDING MATERIALS (NJ) SDN BHD','Project Expense','PJ1069','PUBLIC BANK BHD','3244044409',10.00,10.00,0,'NJSO-00001902','Item Supplies - Delivery Fee','','2026-04-20'), mk('AT2280','out','2026-04-18','WONG CLEANING SERVICE','Project Expense','PJ1078','HONG LEONG BANK BHD','32900002766',1200.00,1200.00,0,'NO. A 6887','Masonry Work','','2026-04-27'), mk('AT2281','out','2026-04-18','H GALLERY SDN BHD','Project Expense','PJ1067','OUB BANK','1333049797',1000.00,1000.00,0,'NVC00156','Photoshooting','','2026-04-20'), mk('AT2282','out','2026-04-18','H GALLERY SDN BHD','Project Expense','PJ1070','OUB BANK','1333049797',1500.00,1500.00,0,'NVC00156','Photoshooting','','2026-04-20'), mk('AT2283','out','2026-04-18','H GALLERY SDN BHD','Project Expense','PJ1071','OUB BANK','1333049797',1500.00,1500.00,0,'NVC00156','Photoshooting','','2026-04-20'), mk('AT2284','out','2026-04-18','H GALLERY SDN BHD','Project Expense','PJ1075','OUB BANK','1333049797',1500.00,1500.00,0,'NVC00156','Photoshooting','','2026-04-20'), mk('AT2285','in','2026-04-18','','Construction Income','PJ1080','','',0,0,256500.00,'','17/4-100000; 17/4-20000; 17/4-40000; 18/4-56500; 18/4-40000','',''), mk('AT2286','in','2026-04-19','','Construction Income','PJ1074','','',0,0,22222.00,'','22/2-6222; 27/2-6000; 4/3-8000; 19/4-2000','',''), mk('AT2287','in','2026-04-16','','Design Income','PJ1078','','',0,0,47900.00,'','','13/4-30000; 16/4-17900',''), mk('AT2288','out','2026-04-20','YONG CHEU CHAI (YAU PLUMBING)','Project Expense','PJ1079','HONG LEONG BANK BHD','32350007593',990.00,990.00,0,'No.3240','Plumbing Work','','2026-04-27'), mk('AT2289','out','2026-04-20','TOCOS LIVING (M) SDN BHD','Project Expense','PJ1078','PUBLIC BANK BHD','3227847315',460.00,460.00,0,'I26-1330','Miscellaneous - Floor Protection','','2026-04-27'), mk('AT2290','out','2026-04-22','FLOORING MASTER ENTERPRISE','Project Expense','PJ1077','PUBLIC BANK BHD','3819644303',7800.00,2730.00,0,'FMQT2604-011','Flooring Work','','2026-04-27'), mk('AT2291','out','2026-04-22','KK & YK PRO PAINTING SDN BHD','Project Expense','PJ1079','UOB Bank','2593008195',8520.00,2556.00,0,'Q2601-025 / I-202603-013','Masonry Work','','2026-04-27'), mk('AT2292','out','2026-04-22','REMARKABLES STRATEGY PLT','Office Expense','','Alliance Bank Berhad','11210013031698',1000.00,1000.00,0,'I-000167','Accounting Fee','','2026-04-27'), mk('AT2293','out','2026-04-22','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1079','HONG LEONG BANK BHD','19701001505',9466.00,1893.20,0,'20260004','M/E Work','','2026-05-05'), mk('AT2294','out','2026-04-22','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1079','HONG LEONG BANK BHD','19701001505',1100.00,1100.00,0,'20260012','M/E Work','','2026-05-05'), mk('AT2295','out','2026-04-24','SILVER RECYCLE SDN BHD','Project Expense','PJ1079','PUBLIC BANK BHD','3241758030',296.80,296.80,0,'SR-2604036','Miscellaneous - Rorobin TNB','','2026-04-27'), mk('AT2296','out','2026-04-24','TNB','Office Expense','','JOMPAY','5454',478.35,478.35,0,'945803161','TNB Electricity Bill - Acct No.210330646604','','2026-04-27'), mk('AT2297','out','2026-04-27','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1062','HONG LEONG BANK','26500050262',2300.00,2300.00,0,'I-202604-0016','Masonry Work','','2026-05-14'), mk('AT2298','out','2026-04-27','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1077','OCBC Bank','7101373179',168.00,168.00,0,'#260416','Miscellaneous - Cleaning','','2026-04-27'), mk('AT2299','out','2026-04-27','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1078','HONG LEONG BANK BHD','12300285671',458.00,458.00,0,'No.1782','Ceiling Work','','2026-04-30'), mk('AT2300','in','2026-04-23','','Government Grant','','','',0,0,1700.00,'','Government Training Incentive programme (TIP) Grant','',''), mk('AT2301','out','2026-04-28','THE BEST OFFICE SOLUTIONS SDN BHD','Office Expense','','PUBLIC BANK BHD','3206535301',487.20,487.20,0,'TB2604106/TB2603094','Copier Machine - Mar & Apr 2026','','2026-04-30'), mk('AT2302','out','2026-04-28','MITALEE CARPET & FURNISHING SDN. BHD.','Project Expense','PJ1059','RHB Bank','20106200020807',150.00,150.00,0,'IV-2605746','Flooring Work - SPC Add-on','','2026-04-28'), mk('AT2303','out','2026-04-28','SENG HO ELECTRICAL SERVICE & TRADING','Project Expense','PJ1077','PUBLIC BANK BHD','3982128208',300.00,300.00,0,'No.8446','Masonry Work - Coring','','2026-04-30'), mk('AT2304','out','2026-04-28','DOUBLE MAN DESIGN','Project Expense','PJ1077','Alliance Bank','11030018199247',11550.00,11550.00,0,'george/1127','Masonry Work','','2026-05-08'), mk('AT2305','out','2026-04-29','LIEW WEI SOON','Office Expense','','AMBANK','4585811294501930',1034.00,1034.00,0,'','Meta Ads - Advertising Fee','','2026-04-30'), mk('AT2306','out','2026-04-29','CC BEST CLEANING SERVICE','Office Expense','','PUBLIC BANK BHD','3243345324',110.00,110.00,0,'','Office Cleaning','','2026-04-30'), mk('AT2307','out','2026-04-29','LIEW WEI SOON','Project Expense','PJ1063','PUBLIC BANK BHD','5379920173386100',1206.50,1206.50,0,'','Item Supplies - Furniture Supplies','','2026-04-30'), mk('AT2308','out','2026-04-29','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',66.00,66.00,0,'','Water Dispenser - Monthly Subscription','','2026-04-30'), ]; const existIds=new Set(ACC_TXNS.map(t=>t.id)); const fresh=rows.filter(r=>!existIds.has(r.id)); if(fresh.length){ACC_TXNS.push(...fresh);saveAccTxns();} localStorage.setItem('inzii_seeded_apr2026','1'); })(); // โ”€โ”€ One-time seed: May 2026 transactions (AT2309โ€“AT2380) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function seedMay2026(){ if(localStorage.getItem('inzii_seeded_may2026'))return; function mk(id,type,date,payee,cat,proj,bank,acc,total,sub,recv,bill,wd,rem,approved){ return{id,type,submittedDate:date,receivedDate:type==='in'?date:'',payeeName:payee||'',category:cat,projectCode:proj||'',bankName:bank||'',bankAccount:acc||'',totalAmount:total||0,submittedAmount:sub||0,amountReceived:recv||0,billNo:bill||'',workDescription:wd||'',remarks:rem||'',subCategories:[],approvedDate:approved||'',projectSplits:[]}; } const rows=[ mk('AT2309','out','2026-05-01','LEE JING WEN','Project Expense','PJ1059','PUBLIC BANK BHD','6803148521',93.58,93.58,0,'','Item Supplies','Accessories','2026-05-02'), mk('AT2310','out','2026-05-01','WONG KHANG CHENG','Project Expense','PJ1062','MAYBANK BERHAD','151294911403',1407.70,1407.70,0,'','Painting Work','Suzuka Coat & Spray Paint','2026-05-02'), mk('AT2311','out','2026-05-01','WONG KHANG CHENG','Project Expense','PJ1063','MAYBANK BERHAD','151294911403',90.80,90.80,0,'','Others','Shipping Fee','2026-05-02'), mk('AT2312','out','2026-05-01','WONG KHANG CHENG','Project Expense','PJ1069','MAYBANK BERHAD','151294911403',31.04,31.04,0,'','Item Supplies','Mailbox','2026-05-02'), mk('AT2313','out','2026-05-01','WONG KHANG CHENG','Project Expense','PJ1077','MAYBANK BERHAD','151294911403',353.68,353.68,0,'','Item Supplies','LED Casing & Floor Trap','2026-05-02'), mk('AT2314','out','2026-05-01','WONG KHANG CHENG','Project Expense','PJ1078','MAYBANK BERHAD','151294911403',358.00,358.00,0,'','Item Supplies','Accessories','2026-05-02'), mk('AT2315','out','2026-05-01','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','6330861511',129.26,129.26,0,'','Groceries','','2026-05-02'), mk('AT2316','out','2026-05-01','LIM HONG MIN','Project Expense','PJ1062','PUBLIC BANK BHD','5008984729',32.98,32.98,0,'','Others','Ducting','2026-05-02'), mk('AT2317','in','2026-05-02','','Construction Income','PJ1079','','',0,0,14291.00,'','','',''), mk('AT2318','in','2026-05-02','','Construction Income','PJ1085','','',0,0,104800.00,'','','',''), mk('AT2319','in','2026-05-04','','Construction Income','PJ1078','','',0,0,30000.00,'','','28/4/2026 - 10000; 04/5/2026 - 20000',''), mk('AT2320','in','2026-05-06','','Construction Income','PJ1079','','',0,0,2570.50,'','Item Supplies','Tiles Supply',''), mk('AT2321','out','2026-05-03','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1069','HONG LEONG BANK BHD','19701001505',12950.00,12950.00,0,'20260015','M/E Work','VO','2026-05-08'), mk('AT2322','out','2026-05-03','Goh Koon Tee','Project Expense','PJ1077','PUBLIC BANK BHD','4235782406',120.00,120.00,0,'No11413','Door & Door Frame','','2026-05-05'), mk('AT2323','out','2026-05-03','SIN SOON HUP FURNITURE SDN BHD','Project Expense','PJ1077','PUBLIC BANK BHD','3176403511',450.00,450.00,0,'CS2604-0004','Door & Door Frame','','2026-05-05'), mk('AT2324','out','2026-05-03','CHAN WAN TENG','Project Expense','PJ1079','MAYBANK BERHAD','114245274403',350.00,350.00,0,'','Flooring Work','SPC Repairing','2026-05-04'), mk('AT2325','out','2026-05-05','3DTECH Solutions Sdn Bhd','Office Expense','','Hong Leong Islamic Bank Berhad','20301000022',7371.00,7371.00,0,'INV-2181/26','Software License','','2026-05-05'), mk('AT2326','out','2026-05-06','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1079','HONG LEONG BANK BHD','12300285671',7906.30,1581.26,0,'No.1747','Ceiling Work','','2026-05-08'), mk('AT2327','out','2026-05-06','MEGA TILES (M) SDN.BHD.','Project Expense','PJ1079','PUBLIC BANK BHD','3236306131',2750.50,2570.50,0,'CN2604-003,IF2603-0002,IF2603-0004,IF2603-0008','Item Supplies','Tiles Supplies','2026-05-08'), mk('AT2328','out','2026-05-06','PRO CLEANING ENTERPRISE','Project Expense','PJ1078','PUBLIC BANK BHD','3242940624',180.00,180.00,0,'NO:202605040003','Miscellaneous','Cleaning','2026-05-08'), mk('AT2329','out','2026-05-06','Lembaga Hasil Dalam Negeri Malaysia','Office Expense','','','',2333.00,2333.00,0,'CP204','','','2026-05-08'), mk('AT2330','out','2026-05-06','Lembaga Hasil Dalam Negeri Malaysia','Salary Expense','','','',1959.10,1959.10,0,'PCB','','','2026-05-08'), mk('AT2331','out','2026-05-06','HRDCorp','Office Expense','','','',334.36,334.36,0,'','Levy','','2026-05-08'), mk('AT2332','out','2026-05-06','KUMPULAN WANG SIMPANAN PEKERJA','Salary Expense','','','',10536.00,10536.00,0,'','KWSP','','2026-05-08'), mk('AT2333','out','2026-05-07','Meng Jiang Trading','Project Expense','PJ1077','Alliance Bank','510780010015680',59040.00,23616.00,0,'QT-000053','Carpentry Work','',''), mk('AT2334','out','2026-05-07','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1079','HONG LEONG BANK','26500050262',8130.00,3130.00,0,'QT-000001','Masonry Work','','2026-05-08'), mk('AT2335','out','2026-05-07','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1059','OCBC Bank','7101373179',880.00,880.00,0,'#260507','Miscellaneous','Cleaning','2026-05-08'), mk('AT2336','out','2026-05-07','PERTUBUHAN KESELAMATAN SOSIAL','Salary Expense','','','',934.30,934.30,0,'','SOCSO & EIS','',''), mk('AT2337','out','2026-05-11','SDR (HORIZON) SDN.BHD.','Project Expense','PJ1078','MAYBANK BERHAD','551100851092',3350.00,1675.00,0,'SO-2604-0001','Door & Door Frame','','2026-05-11'), mk('AT2338','out','2026-05-11','BH 93 Enterprise','Project Expense','PJ1059','HONG LEONG BANK BHD','13900111821',280.00,280.00,0,'No.I2004329','Miscellaneous','Rorobin','2026-05-11'), mk('AT2339','out','2026-05-11','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1078','OCBC Bank','7161154406',6900.00,6900.00,0,'INV2604/0098','Painting Work','','2026-05-11'), mk('AT2340','out','2026-05-11','ROOFTOP WATERPROOFING MNC SDN BHD','Project Expense','PJ1079','OCBC Bank','7161154406',9570.00,4785.00,0,'INV2605/0114','Painting Work','','2026-05-11'), mk('AT2341','out','2026-05-11','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1085','HONG LEONG BANK','26500050262',25680.00,15000.00,0,'QT-000006','Masonry Work','',''), mk('AT2342','out','2026-05-11','BOO FURNITURE SDN BHD','Project Expense','PJ1085','OCBC Bank','1161017973',4500.00,2250.00,0,'SO26-0049','Door & Door Frame','','2026-05-11'), mk('AT2343','out','2026-05-14','SHIEN FENG RENOVATION ENTERPRISE','Project Expense','PJ1077','Hong Leong Bank BHD','900132748',26475.00,26475.00,0,'20260012','Tiles Work','','2026-06-05'), mk('AT2344','out','2026-05-14','DDS ALUDNA SDN BHD','Project Expense','PJ1079','Hong Leong Bank','36500069428',5390.00,2695.00,0,'INV2603-018','Aluminium Work','','2026-05-14'), mk('AT2345','out','2026-05-14','Matex Acrylic Sdn Bhd','Project Expense','PJ1077','RHB Bank','20106200106507',1720.00,1720.00,0,'13/05/26','Carpentry Work','Acrylic Display','2026-05-14'), mk('AT2346','out','2026-05-14','RANHILL SAJ','Office Expense','','JomPAY','3673',41.50,41.50,0,'J26041','','Account No.85952418J8250064 SAJ','2026-05-14'), mk('AT2347','out','2026-05-12','CHWEE HWA NURSERY SDN BHD','Project Expense','PJ1063','Alliance Bank','11300011835060',58843.00,10000.00,0,'I-202602-055','Landscape','','2026-05-14'), mk('AT2348','out','2026-05-15','Walden Lighting Solution','Project Expense','PJ1063','CIMB Bank','8605351356',27565.00,27565.00,0,'#N00140/IV-00963','Item Supplies','Light Supply','2026-05-15'), mk('AT2349','out','2026-05-15','DOUBLE MAN DESIGN','Project Expense','PJ1080','Alliance Bank','11030018199247',107875.00,30000.00,0,'george/0325','Masonry Work','','2026-05-15'), mk('AT2350','out','2026-05-12','AT WOOD FURNITURE','Project Expense','PJ1063','PUBLIC BANK BHD','3212349003',252606.50,10000.00,0,'ATW/INV/2510-001','Carpentry Work','','2026-05-15'), mk('AT2351','out','2026-05-15','LHDNM','Office Expense','','','',10.00,10.00,0,'F1A517729772','Staff Stamping Fee','','2026-05-17'), mk('AT2352','out','2026-05-18','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1063','HONG LEONG BANK','26500050262',250.00,250.00,0,'I-202605-0007','Others','Unpack Taobao','2026-05-19'), mk('AT2353','out','2026-05-18','LIM HF CONSTRUCTION','Project Expense','PJ1077','HONG LEONG BANK BHD','12300297360',17562.75,5378.99,0,'QN25-00106 / 2605/004','Ceiling Work','','2026-05-22'), mk('AT2354','in','2026-05-12','','Project Income','PJ1063','','',0,0,3000.00,'','Management Refund','',''), mk('AT2355','in','2026-05-19','','Design Income','PJ1084','','',0,0,6700.00,'','','',''), mk('AT2356','in','2026-05-20','','Design Income','PJ1088','','',0,0,6000.00,'','','',''), mk('AT2357','in','2026-05-24','','Design Income','PJ1089','','',0,0,6000.00,'','','',''), mk('AT2358','in','2026-05-23','','Design Income','PJ1090','','',0,0,10000.00,'','','',''), mk('AT2359','in','2026-05-21','','Government Grant','','','',0,0,1700.00,'','','Government Training Incentive programme (TIP) Grant',''), mk('AT2360','out','2026-05-19','DDS ALUDNA SDN BHD','Project Expense','PJ1078','Hong Leong Bank','36500069428',11240.00,5620.00,0,'20260408001','Aluminium Work','','2026-06-05'), mk('AT2361','out','2026-05-19','THE BEST SANITARYWARE TRADING','Project Expense','PJ1059','Hong Leong Bank','21900011095',475.00,475.00,0,'CS26-000274','Item Supplies','Sanitary Ware Supply','2026-05-19'), mk('AT2362','out','2026-05-19','SHIEN FENG RENOVATION ENTERPRISE','Project Expense','PJ1063','Hong Leong Bank BHD','900132748',2850.00,2850.00,0,'20260011','Tiles Work','','2026-05-19'), mk('AT2363','out','2026-05-21','JAWS WOO ELECTRICAL','Project Expense','PJ1077','HONG LEONG BANK','12300280748',16435.00,2427.00,0,'22/01/2026','M/E Work','',''), mk('AT2364','out','2026-05-23','WH WOOD SPECIALIST INTERIOR','Project Expense','PJ1059','HONG LEONG BANK BHD','21900041577',600.00,600.00,0,'WH2026-04-003','Flooring Work','SPC Touch Up',''), mk('AT2365','out','2026-05-28','CHWEE HWA NURSERY SDN BHD','Project Expense','PJ1063','Alliance Bank','11300011835060',58843.00,1259.50,0,'I-202602-055','Landscape','Balance Payment','2026-05-30'), mk('AT2366','out','2026-05-29','LIM QIAN WEN','Project Expense','PJ1079','PUBLIC BANK BHD','1011420592148',239.01,239.01,0,'','Others','Taobao Furniture - Gift','2026-06-01'), mk('AT2367','out','2026-05-29','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','1011420592148',50.00,50.00,0,'','Medical Claim','','2026-06-01'), mk('AT2368','out','2026-05-29','LIM QIAN WEN','Office Expense','','PUBLIC BANK BHD','1011420592148',35.14,35.14,0,'','CCTV Adapter','Office Upkeep','2026-06-01'), mk('AT2369','out','2026-05-29','TOCOS LIVING (M) SDN BHD','Project Expense','PJ1078','PUBLIC BANK BHD','3227847315',13420.00,4026.00,0,'I26-1326','Flooring Work','','2026-06-05'), mk('AT2370','out','2026-05-30','WONG KHANG CHENG','Project Expense','PJ1077','MAYBANK BERHAD','151294911403',15.44,15.44,0,'','Others','stainless steel ducting cup','2026-06-01'), mk('AT2371','out','2026-05-30','WONG KHANG CHENG','Project Expense','PJ1078','MAYBANK BERHAD','151294911403',15.10,15.10,0,'','Others','lalamove switch','2026-06-01'), mk('AT2372','out','2026-05-30','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',82.00,82.00,0,'','Site Use','','2026-06-01'), mk('AT2373','out','2026-05-30','WONG KHANG CHENG','Office Expense','','MAYBANK BERHAD','151294911403',11.16,11.16,0,'','Groceries','','2026-06-01'), mk('AT2374','out','2026-05-25','CHWEE HWA NURSERY SDN BHD','Project Expense','PJ1063','Alliance Bank','11300011835060',58843.00,10000.00,0,'I-202602-055','Landscape','','2026-05-27'), mk('AT2375','out','2026-05-26','AT WOOD FURNITURE','Project Expense','PJ1079','PUBLIC BANK BHD','3212349003',30585.00,6117.00,0,'ATW/INV/2602-005','Carpentry Work','','2026-06-05'), mk('AT2376','out','2026-05-26','STONETOP RENOVATION','Project Expense','PJ1079','HONG LEONG BANK BHD','18100109205',3689.00,3689.00,0,'26/03/1938','Table Top','','2026-05-27'), mk('AT2377','out','2026-05-27','DOUBLE MAN DESIGN','Project Expense','PJ1069','Alliance Bank','11030018199247',214472.00,50000.00,0,'george/1001','Masonry Work','',''), mk('AT2378','out','2026-05-27','TOCOS LIVING (M) SDN BHD','Project Expense','PJ1078','PUBLIC BANK BHD','3227847315',300.00,300.00,0,'I26-1351','Flooring Work','','2026-06-05'), mk('AT2379','out','2026-05-27','STONETOP RENOVATION','Project Expense','PJ1078','HONG LEONG BANK BHD','18100109205',6915.00,6915.00,0,'26/05/1943','Table Top','',''), mk('AT2380','out','2026-05-30','CC BEST CLEANING SERVICE','Office Expense','','Public Bank Berhad','3243345324',220.00,220.00,0,'C1250','Office Cleaning','','2026-06-01'), ]; const existIds=new Set(ACC_TXNS.map(t=>t.id)); const fresh=rows.filter(r=>!existIds.has(r.id)); if(fresh.length){ACC_TXNS.push(...fresh);saveAccTxns();} localStorage.setItem('inzii_seeded_may2026','1'); })(); // โ”€โ”€ One-time seed: June 2026 transactions (AT2381โ€“AT2414) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function seedJun2026(){ if(localStorage.getItem('inzii_seeded_jun2026'))return; function mk(id,type,date,payee,cat,proj,bank,acc,total,sub,recv,bill,wd,rem,approved){ return{id,type,submittedDate:date,receivedDate:type==='in'?date:'',payeeName:payee||'',category:cat,projectCode:proj||'',bankName:bank||'',bankAccount:acc||'',totalAmount:total||0,submittedAmount:sub||0,amountReceived:recv||0,billNo:bill||'',workDescription:wd||'',remarks:rem||'',subCategories:[],approvedDate:approved||'',projectSplits:[]}; } const rows=[ mk('AT2381','out','2026-06-02','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',226.80,226.80,0,'','GOOGLE WORKSPACE - MONTHLY SUBSCRIPTION','','2026-06-05'), mk('AT2382','out','2026-06-02','LIEW WEI SOON','Office Expense','','PUBLIC BANK BHD','5379920173386100',66.00,66.00,0,'','WATER DISPENSER - MONTHLY SUBSCRIPTION','','2026-06-05'), mk('AT2383','out','2026-06-03','BH 93 ENTERPRISE','Project Expense','PJ1077','HONG LEONG BANK BHD','13900111821',560.00,560.00,0,'No.I2004433','MISCELLANEOUS - ROROBIN','','2026-06-05'), mk('AT2384','out','2026-06-04','REMARKABLES STRATEGY PLT','Office Expense','','Alliance Bank Berhad','11210013031698',1500.00,1500.00,0,'I-000181','ACCOUNTING FEE','','2026-06-05'), mk('AT2385','out','2026-06-04','FLOORING MASTER ENTERPRISE','Project Expense','PJ1062','PUBLIC BANK BHD','3819644303',19400.00,3000.00,0,'FMQT0126-015','FLOORING WORK','','2026-06-05'), mk('AT2386','out','2026-06-05','TNB','Office Expense','','JOMPAY','5454',387.70,387.70,0,'174421455','TNB ELECTRICITY BILL','Account No.210330646604','2026-06-05'), mk('AT2387','out','2026-06-05','RANHILL SAJ','Office Expense','','JOMPAY','3673',41.50,41.50,0,'J26051','SAJ WATER BILL','Account No.85952418J8250064','2026-06-05'), mk('AT2388','out','2026-06-05','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1077','OCBC Bank','7101373179',980.00,980.00,0,'#260528','MISCELLANEOUS - CLEANING','','2026-06-08'), mk('AT2389','out','2026-06-05','DDS ALUDNA SDN BHD','Project Expense','PJ1069','Hong Leong Bank','36500069428',25280.00,12640.00,0,'DDS 20260527001','ALUMINIUM WORK','','2026-06-19'), mk('AT2390','in','2026-06-02','','Design Income','PJ1081','','',0,0,8000.00,'','','',''), mk('AT2391','in','2026-06-01','','Design Income','PJ1082','','',0,0,10500.00,'','','',''), mk('AT2392','in','2026-06-06','','Construction Income','PJ1078','','',0,0,70000.00,'','','5/6/26 - 50000; 6/6/26 - 20000',''), mk('AT2393','in','2026-06-09','','Construction Income','PJ1077','','',0,0,51000.00,'','','',''), mk('AT2394','in','2026-06-19','','Construction Income','PJ1085','','',0,0,75750.00,'','','',''), mk('AT2395','out','2026-06-08','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1059','OCBC Bank','7101373179',150.00,150.00,0,'#260519','MISCELLANEOUS - CLEANING','','2026-06-08'), mk('AT2396','out','2026-06-08','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Office Expense','','','',2333.00,2333.00,0,'CP204','INCOME TAX (CP204)','','2026-06-08'), mk('AT2397','out','2026-06-08','LEMBAGA HASIL DALAM NEGERI MALAYSIA','Salary Expense','','','',1503.15,1503.15,0,'PCB','SALARY PCB','','2026-06-08'), mk('AT2398','out','2026-06-08','HRDCORP','Office Expense','','','',305.43,305.43,0,'LEVY','HRD LEVY','','2026-06-08'), mk('AT2399','out','2026-06-08','KUMPULAN WANG SIMPANAN PEKERJA','Salary Expense','','','',10664.00,10664.00,0,'KWSP','EPF PAYMENT','','2026-06-08'), mk('AT2400','out','2026-06-08','LIEW WEI SOON','Office Expense','','HONG LEONG BANK BHD','7050209799',613.22,613.22,0,'','META ADS - ADVERTISING FEE','','2026-06-08'), mk('AT2401','out','2026-06-08','PERTUBUHAN KESELAMATAN SOSIAL','Salary Expense','','','',849.50,849.50,0,'SOCSO & EIS','SOCSO & EIS PAYMENT','','2026-06-08'), mk('AT2402','out','2026-06-12','DOUBLE MAN DESIGN','Project Expense','PJ1080','Alliance Bank','11030018199247',107875.00,20000.00,0,'george/0325','MASONRY WORK','','2026-06-15'), mk('AT2403','out','2026-06-12','DDS ALUDNA SDN BHD','Project Expense','PJ1077','Hong Leong Bank','36500069428',7000.00,7000.00,0,'INV2606-002','ALUMINIUM WORK','','2026-06-15'), mk('AT2404','out','2026-06-12','UNITAE ENTERPRISE','Project Expense','PJ1077','Standard Chartered Bank','668194687188',4100.00,4100.00,0,'202606-015','DECKING WORK','','2026-06-15'), mk('AT2405','out','2026-06-12','KIM YAP ENGINEERING SDN BHD','Project Expense','PJ1077','PUBLIC BANK BHD','3236679205',13900.00,13900.00,0,'IV0626-03','METAL & AWNING WORK','','2026-06-22'), mk('AT2406','out','2026-06-12','KIM YAP ENGINEERING SDN BHD','Project Expense','PJ1078','PUBLIC BANK BHD','3236679205',25300.00,25300.00,0,'IV0626-04','METAL & AWNING WORK','',''), mk('AT2407','out','2026-06-12','NOON PLASTER CEILING & RENOVATION','Project Expense','PJ1085','HONG LEONG BANK BHD','12300285671',10430.10,5215.05,0,'No1817','CEILING & PARTITION WORK','','2026-06-15'), mk('AT2408','out','2026-06-15','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1078','HONG LEONG BANK BHD','19701001505',22955.00,6239.00,0,'260003','M/E WORK','',''), mk('AT2409','out','2026-06-15','SHENG CHEW FITMENT ENTERPRISE','Project Expense','PJ1085','HONG LEONG BANK BHD','19701001505',16425.00,13140.00,0,'20260017','M/E WORK','','2026-06-19'), mk('AT2410','out','2026-06-22','REMARKABLES STRATEGY PLT','Office Expense','','Alliance Bank Berhad','11210013031698',1000.00,1000.00,0,'I-000193','ACCOUNTING FEE','','2026-06-22'), mk('AT2411','out','2026-06-22','TICLEAN CLEANING SERVICE ENTERPRISE','Project Expense','PJ1078','OCBC Bank','7101373179',980.00,980.00,0,'Invoice #260611','MISCELLANEOUS - CLEANING','','2026-06-22'), mk('AT2412','out','2026-06-22','WONG CLEANING SERVICE','Project Expense','PJ1078','HONG LEONG BANK BHD','32900002766',400.00,400.00,0,'NO.A 6909','MASONRY WORK','FLOOR POLISH','2026-06-22'), mk('AT2413','out','2026-06-22','ACTINIUM ENGINEERING & PROJECT SDN BHD','Project Expense','PJ1085','Maybank Berhad','551623217044',12303.00,6151.50,0,'Act26 - 1113','STAINLESS STEEL WORK','','2026-06-22'), mk('AT2414','out','2026-06-24','HONGYE RENOVATION & CONSTRUCTION SDN. BHD.','Project Expense','PJ1085','HONG LEONG BANK','26500050262',25680.00,5000.00,0,'QT-000006','MASONRY WORK','',''), ]; const existIds=new Set(ACC_TXNS.map(t=>t.id)); const fresh=rows.filter(r=>!existIds.has(r.id)); if(fresh.length){ACC_TXNS.push(...fresh);saveAccTxns();} localStorage.setItem('inzii_seeded_jun2026','1'); })(); // โ”€โ”€ One-time: fix IN transactions missing receivedDate โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function fixInReceivedDates(){ let fixed=0; ACC_TXNS.forEach(t=>{ if(t.type==='in'&&!t.receivedDate&&t.submittedDate){ t.receivedDate=t.submittedDate;fixed++; } }); if(fixed){saveAccTxns();} })(); // โ”€โ”€ Normalise fixed recurring payment suppliers (idempotent) โ”€โ”€โ”€โ”€โ”€ (function normaliseFixedPayments(){ const LHDN='LEMBAGA HASIL DALAM NEGERI MALAYSIA'; let changed=false; ACC_TXNS.forEach(t=>{ // 1. Payee name normalisation const pn=(t.payeeName||'').trim(); if(pn!==LHDN&&(pn.toUpperCase()==='LEMBAGA HASIL DALAM NEGERI MALAYSIA'||pn==='LHDNM')){ t.payeeName=LHDN;changed=true; } if(pn!=='HRDCORP'&&pn.toUpperCase()==='HRDCORP'){ t.payeeName='HRDCORP';changed=true; } const p=(t.payeeName||'').trim().toUpperCase(); // 2. KWSP โ€“ Kumpulan Wang Simpanan Pekerja if(p==='KUMPULAN WANG SIMPANAN PEKERJA'){ if(t.category!=='Salary Expense'){t.category='Salary Expense';changed=true;} if(t.billNo!=='KWSP'){t.billNo='KWSP';changed=true;} if(t.workDescription!=='EPF PAYMENT'){t.workDescription='EPF PAYMENT';changed=true;} } // 3. SOCSO/EIS โ€“ Pertubuhan Keselamatan Sosial if(p==='PERTUBUHAN KESELAMATAN SOSIAL'){ if(t.category!=='Salary Expense'){t.category='Salary Expense';changed=true;} if(t.billNo!=='SOCSO & EIS'){t.billNo='SOCSO & EIS';changed=true;} if(t.workDescription!=='SOCSO & EIS PAYMENT'){t.workDescription='SOCSO & EIS PAYMENT';changed=true;} if(t.remarks==='SOSCO & EIS'){t.remarks='SOCSO & EIS';changed=true;} } // 4. HRD Corp Levy if(p==='HRDCORP'){ if(t.billNo!=='LEVY'){t.billNo='LEVY';changed=true;} if(t.workDescription!=='HRD LEVY'){t.workDescription='HRD LEVY';changed=true;} } // 5. LHDN โ€“ work descriptions and categories by bill type if(p===LHDN||p==='LEMBAGA HASIL DALAM NEGERI MALAYSIA'){ if(t.billNo==='CP204'&&t.workDescription!=='INCOME TAX (CP204)'){t.workDescription='INCOME TAX (CP204)';changed=true;} if(t.billNo==='PCB'){ if(t.workDescription!=='SALARY PCB'){t.workDescription='SALARY PCB';changed=true;} if(t.category!=='Salary Expense'){t.category='Salary Expense';changed=true;} } } // 6. TNB โ€“ standardise bank & work description if(p==='TNB'){ if(t.bankName==='JomPAY'){t.bankName='JOMPAY';changed=true;} if((t.workDescription||'').toUpperCase()==='ELECTRICITY BILL'){t.workDescription='TNB ELECTRICITY BILL';changed=true;} } // 7. RANHILL SAJ โ€“ standardise bank & work description if(p==='RANHILL SAJ'){ if(t.bankName==='JomPAY'){t.bankName='JOMPAY';changed=true;} const wd=(t.workDescription||'').toUpperCase(); if(!wd||wd==='WATER BILL'||wd==='SAJ'){t.workDescription='SAJ WATER BILL';changed=true;} } }); if(changed)saveAccTxns(); })(); // โ”€โ”€ Normalise work descriptions (idempotent) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (function normaliseWorkDescriptions(){ // Map: uppercase input โ†’ canonical uppercase output const map={ // Ceiling 'CEILING WORK':'CEILING & PARTITION WORK', // Miscellaneous sub-types (short form โ†’ full form) 'CLEANING':'MISCELLANEOUS - CLEANING', 'ROROBIN':'MISCELLANEOUS - ROROBIN', 'FLOORGARD':'MISCELLANEOUS - FLOORGARD', // Tiles consistency 'TILE WORK':'TILES WORK', 'TILES SUPPLIES':'ITEM SUPPLIES - TILES SUPPLY', // Monthly recurring โ€” use full descriptive name 'COPIER MACHINE':'COPIER MACHINE - MONTHLY SUBSCRIPTION', 'COPIER MACHINE RENTAL FEE':'COPIER MACHINE - MONTHLY SUBSCRIPTION', 'GOOGLE WORKSPACE':'GOOGLE WORKSPACE - MONTHLY SUBSCRIPTION', 'WATER DISPENSER':'WATER DISPENSER - MONTHLY SUBSCRIPTION', // TNB / SAJ already handled by normaliseFixedPayments but add here for safety 'ELECTRICITY BILL':'TNB ELECTRICITY BILL', 'WATER BILL':'SAJ WATER BILL', // Salary PCB โ€” ensure uppercase 'SALARY PCB':'SALARY PCB', 'EPF PAYMENT':'EPF PAYMENT', 'SOCSO & EIS PAYMENT':'SOCSO & EIS PAYMENT', 'HRD LEVY':'HRD LEVY', 'INCOME TAX':'INCOME TAX (CP204)', }; let changed=false; ACC_TXNS.forEach(t=>{ if(!t.workDescription)return; const up=t.workDescription.trim().toUpperCase(); const canonical=map[up]||up; // default: just uppercase if(t.workDescription!==canonical){t.workDescription=canonical;changed=true;} }); if(changed)saveAccTxns(); })(); // โ”€โ”€ Backfill workDescription from projectSplits (idempotent) โ”€โ”€โ”€โ”€โ”€ (function backfillWorkDescription(){ let fixed=0; ACC_TXNS.forEach(t=>{ if(t.workDescription)return; // already has a description const sp=t.projectSplits&&t.projectSplits[0]; if(!sp)return; const cat=sp.category||''; const desc=sp.description||''; if(!cat&&!desc)return; t.workDescription=cat&&desc?`${cat} - ${desc}`:cat||desc; fixed++; }); if(fixed)saveAccTxns(); })(); // โ”€โ”€ Supplier name deduplication (runs every load, idempotent) โ”€โ”€โ”€โ”€ (function deduplicateSuppliers(){ // canonical name map (key = uppercased input) โ†’ correct final name (always UPPERCASE) const renames={ 'VIP LIGHTING AND SERVICES':'VIP LIGHTING & SERVICES', 'TGS FURNISHINGS SDN. BHD.':'TGS FURNISHINGS SDN BHD', 'TM SANITARY SDN. BHD':'TM SANITARY SDN. BHD.', 'TM SANITARY SDN. BND.':'TM SANITARY SDN. BHD.', }; let changed=false; // Step 1: uppercase + rename all payee names in transactions ACC_TXNS.forEach(t=>{ if(!t.payeeName)return; const up=t.payeeName.trim().toUpperCase(); const canonical=renames[up]||up; if(t.payeeName!==canonical){t.payeeName=canonical;changed=true;} }); if(changed)saveAccTxns(); // Step 2: uppercase + rename all supplier names let spChanged=false; SUPPLIERS.forEach(s=>{ if(!s.companyName)return; const up=s.companyName.trim().toUpperCase(); const canonical=renames[up]||up; if(s.companyName!==canonical){s.companyName=canonical;spChanged=true;} }); // Step 3: merge duplicates โ€” keep first entry, absorb bank info from later duplicates const seen=new Map(); SUPPLIERS.forEach(s=>{ const key=(s.companyName||'').trim().toUpperCase(); if(!seen.has(key)){ seen.set(key,s); } else { // Merge any bank/contact details the first entry is missing const first=seen.get(key); if(!first.bankName&&s.bankName){first.bankName=s.bankName;spChanged=true;} if(!first.bankAccount&&s.bankAccount){first.bankAccount=s.bankAccount;spChanged=true;} if(!first.companyPhone&&s.companyPhone){first.companyPhone=s.companyPhone;spChanged=true;} if(!first.email&&s.email){first.email=s.email;spChanged=true;} if(!first.regNo&&s.regNo){first.regNo=s.regNo;spChanged=true;} spChanged=true; // duplicate found, list will shrink } }); const deduped=[...seen.values()]; if(deduped.length!==SUPPLIERS.length||spChanged){ SUPPLIERS.length=0;SUPPLIERS.push(...deduped);saveSuppliers(); } })(); // โ”€โ”€ One-time: sync all OUT transaction payees โ†’ Supplier Details โ”€โ”€ (function syncPayeesToSuppliers(){ if(localStorage.getItem('inzii_payee_sync_v1'))return; let added=0; ACC_TXNS.filter(t=>t.type==='out'&&t.payeeName).forEach(t=>{ const norm=t.payeeName.trim().toUpperCase(); if(!SUPPLIERS.find(s=>(s.companyName||'').trim().toUpperCase()===norm)){ if(t.bankName&&!ACC_BANKS.includes(t.bankName)){ACC_BANKS.push(t.bankName);saveAccBanks();} SUPPLIERS.push({id:supplierNextId(),companyName:t.payeeName.trim(),bankName:t.bankName||'',bankAccount:t.bankAccount||'',companyPhone:'',contactPerson:'',email:'',regNo:'',tinNo:'',sstNo:'',irbMsicCode:'',createdAt:new Date().toISOString()}); added++; } }); if(added){saveSuppliers();} localStorage.setItem('inzii_payee_sync_v1','1'); })(); // โ”€โ”€ One-time: approve TM UNIFI Febโ€“Jun 2026 payments โ”€โ”€ (function approveTmUnifiFebJun(){ if(localStorage.getItem('inzii_unifi_approve_feb_jun'))return; let changed=false; ACC_TXNS.forEach(t=>{ const pn=(t.payeeName||'').trim().toUpperCase(); if(!pn.includes('UNIFI'))return; if(t.type!=='out')return; const d=t.submittedDate||''; if(d>='2026-02-01'&&d<='2026-06-30'&&!t.approvedDate){ t.approvedDate=d;changed=true; } }); if(changed)saveAccTxns(); localStorage.setItem('inzii_unifi_approve_feb_jun','1'); })(); // โ”€โ”€ One-time: move MAXIS Jan 1 โ†’ Dec 1, set pending โ”€โ”€ (function fixMaxisJanToDec(){ if(localStorage.getItem('inzii_maxis_jan_to_dec'))return; const t=ACC_TXNS.find(x=>(x.payeeName||'').trim().toUpperCase()==='MAXIS'&&x.submittedDate==='2026-01-01'); if(t){t.submittedDate='2026-12-01';t.approvedDate='';saveAccTxns();} localStorage.setItem('inzii_maxis_jan_to_dec','1'); })(); // โ”€โ”€ Idempotent: auto-approve all isRecurring past transactions (MAXIS, UNIFI etc) โ”€โ”€ (function autoApproveRecurring(){ const today=new Date().toISOString().slice(0,10); let changed=false; ACC_TXNS.forEach(t=>{ if(!t.isRecurring)return; if(t.type==='out'&&!t.approvedDate&&t.submittedDate&&t.submittedDate<=today){ t.approvedDate=t.submittedDate;changed=true; } }); if(changed)saveAccTxns(); })(); // โ”€โ”€ Idempotent: tag MAXIS & UNIFI as isRecurring (entered before flag existed) โ”€โ”€ (function tagLegacyRecurring(){ const RECURRING_PAYEES=['MAXIS','UNIFI','TM UNIFI']; let changed=false; ACC_TXNS.forEach(t=>{ const pn=(t.payeeName||'').trim().toUpperCase(); if(RECURRING_PAYEES.includes(pn)&&!t.isRecurring){ t.isRecurring=true;changed=true; } }); if(changed)saveAccTxns(); })(); // โ”€โ”€ Tag car loan (LIEW WEI SOON, amt=2189) + office rental (K-UNIS) as recurring โ”€โ”€ (function tagCarLoanAndRental(){ let changed=false; ACC_TXNS.forEach(t=>{ if(t.type!=='out'||t.isRecurring)return; const pn=(t.payeeName||'').trim().toUpperCase(); if(pn==='LIEW WEI SOON'&&t.submittedAmount===2189){t.isRecurring=true;changed=true;} if(pn==='K-UNIS MARKETING (M) SDN BHD'){t.isRecurring=true;changed=true;} }); if(changed)saveAccTxns(); })(); // โ”€โ”€ Idempotent: fix MAXIS recurring โ€” 1st of month, auto-approve past dates โ”€โ”€ (function fixMaxisRecurring(){ const today=new Date().toISOString().slice(0,10); let changed=false; ACC_TXNS.forEach(t=>{ const pn=(t.payeeName||'').trim().toUpperCase(); if(pn!=='MAXIS')return; const df=t.type==='out'?'submittedDate':'receivedDate'; const d=t[df]||''; if(!d)return; // Move to 1st of the same month const first=d.slice(0,7)+'-01'; if(t[df]!==first){t[df]=first;changed=true;} // Auto-approve if date has passed or is today if(t.type==='out'&&!t.approvedDate&&t.submittedDate&&t.submittedDate<=today){ t.approvedDate=t.submittedDate;changed=true; } }); if(changed)saveAccTxns(); })(); // โ”€โ”€ Idempotent: backfill projectCode for income txns from projectSplits โ”€โ”€ (function backfillIncomeProjectCode(){ let changed=false; ACC_TXNS.forEach(t=>{ if(t.type!=='in')return; // If projectCode is already set, skip if(t.projectCode)return; // Try to get from projectSplits const code=(t.projectSplits||[]).find(s=>s.code)?.code||''; if(code){t.projectCode=code;changed=true;} }); if(changed)saveAccTxns(); })(); // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // PAYMENT VOUCHER // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function pvPage(){ return`

Payment Voucher

PV NoDatePayeePurposeProjectMethodAmount (MYR)StatusPrepared By
`; } function renderPVs(){ const q=(document.getElementById('pv_q')?.value||'').toLowerCase(); const st=document.getElementById('pv_status')?.value||''; const mo=document.getElementById('pv_month')?.value||''; // populate month filter const sel=document.getElementById('pv_month'); if(sel&&sel.options.length===1){ const months=[...new Set(PV_LIST.map(p=>p.date?.slice(0,7)).filter(Boolean))].sort().reverse(); months.forEach(m=>{const o=document.createElement('option');o.value=m;o.textContent=m;sel.appendChild(o);}); } let list=PV_LIST.filter(p=>{ if(st&&p.status!==st)return false; if(mo&&!(p.date||'').startsWith(mo))return false; if(q){const h=[p.pvNo,p.payee,p.purpose,p.projectCode,p.preparedBy].join(' ').toLowerCase();if(!h.includes(q))return false;} return true; }).sort((a,b)=>(b.pvNo||'').localeCompare(a.pvNo||'')); document.getElementById('pv_count').textContent=list.length+' record'+(list.length!==1?'s':''); const statusColor={Draft:'var(--muted)',Approved:'var(--blue)',Paid:'var(--green)'}; document.getElementById('pv_tbody').innerHTML=list.map(p=>` ${p.pvNo||'โ€”'} ${p.date||'โ€”'} ${p.payee||'โ€”'} ${p.purpose||'โ€”'} ${p.projectCode||'โ€”'} ${p.paymentMethod||'โ€”'} ${RM(p.amount||0)} ${p.status||'Draft'} ${p.preparedBy||'โ€”'} `).join(''); } function openPVModal(id){ const pv=id?PV_LIST.find(p=>p.id===id):null; const today=new Date().toISOString().slice(0,10); document.getElementById('mt').textContent=pv?`Edit Payment Voucher โ€” ${pv.pvNo}`:'New Payment Voucher'; document.getElementById('md').style.maxWidth='700px'; document.getElementById('mb').innerHTML=`
${pv?``:''}
`; document.getElementById('mo').classList.add('show'); } function savePV(id){ const pvNo=document.getElementById('pv_no').value.trim(); const date=document.getElementById('pv_date').value; const payee=document.getElementById('pv_payee').value.trim(); const amount=parseFloat(document.getElementById('pv_amount').value)||0; const purpose=document.getElementById('pv_purpose').value.trim(); if(!date||!payee||!purpose){toast('Please fill Date, Payee and Purpose','var(--red)');return;} const data={ id:id||('PV'+Date.now()),pvNo,date,payee,amount, paymentMethod:document.getElementById('pv_method').value, projectCode:document.getElementById('pv_proj').value.trim(), purpose, preparedBy:document.getElementById('pv_prepared').value.trim(), approvedBy:document.getElementById('pv_approved').value.trim(), status:document.getElementById('pv_stat').value, remarks:document.getElementById('pv_remarks').value.trim(), }; if(id){const i=PV_LIST.findIndex(p=>p.id===id);if(i>=0)PV_LIST[i]=data;} else PV_LIST.unshift(data); savePVs();closeModal();renderPVs(); toast('โœ… Payment Voucher saved'); } function deletePV(id){ if(!confirm('Delete this Payment Voucher?'))return; PV_LIST=PV_LIST.filter(p=>p.id!==id);savePVs();renderPVs();toast('Deleted'); } function printPV(id){ const pv=PV_LIST.find(p=>p.id===id);if(!pv)return; const f=v=>(+(v||0)).toLocaleString('en-MY',{minimumFractionDigits:2,maximumFractionDigits:2}); const w=window.open('','_blank');if(!w)return; w.document.write(` ${pv.pvNo} โ€“ Payment Voucher
${CO.name}
${CO.addr1}
${CO.addr2}
Tel: ${CO.phone} | Email: ${CO.email}

Payment Voucher

${pv.pvNo}
Date: ${pv.date}
${pv.status||'Draft'}
Payment Details
Payee${pv.payee}
Payment Method${pv.paymentMethod||'โ€”'}
${pv.projectCode?`
Project Code${pv.projectCode}
`:''}
Purpose / Description${pv.purpose||'โ€”'}
${pv.remarks?`
Remarks${pv.remarks}
`:''}
TOTAL AMOUNT (MYR) RM ${f(pv.amount)}
In words: ${_numToWords(pv.amount||0)} Only
Prepared By
${pv.preparedBy||'___________________________'}
Signature / Date
Approved By
${pv.approvedBy||'___________________________'}
Signature / Date
`); w.document.close(); setTimeout(()=>w.print(),400); } function pvExportExcel(){ const rows=[['PV No','Date','Payee','Purpose','Project','Method','Amount (MYR)','Status','Prepared By','Approved By','Remarks']]; PV_LIST.forEach(p=>rows.push([p.pvNo||'',p.date||'',p.payee||'',p.purpose||'',p.projectCode||'',p.paymentMethod||'',+(p.amount||0),p.status||'',p.preparedBy||'',p.approvedBy||'',p.remarks||''])); _csvDownload(rows,'PaymentVouchers'); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // CREDIT NOTE // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• function cnPage(){ return`

Credit Note

CN NoDateClientRef InvoiceReasonAmount (MYR)StatusAuthorised By
`; } function renderCNs(){ const q=(document.getElementById('cn_q')?.value||'').toLowerCase(); const st=document.getElementById('cn_status')?.value||''; const mo=document.getElementById('cn_month')?.value||''; const sel=document.getElementById('cn_month'); if(sel&&sel.options.length===1){ const months=[...new Set(CN_LIST.map(c=>c.date?.slice(0,7)).filter(Boolean))].sort().reverse(); months.forEach(m=>{const o=document.createElement('option');o.value=m;o.textContent=m;sel.appendChild(o);}); } let list=CN_LIST.filter(c=>{ if(st&&c.status!==st)return false; if(mo&&!(c.date||'').startsWith(mo))return false; if(q){const h=[c.cnNo,c.client,c.refInvoice,c.reason,c.authorizedBy].join(' ').toLowerCase();if(!h.includes(q))return false;} return true; }).sort((a,b)=>(b.cnNo||'').localeCompare(a.cnNo||'')); document.getElementById('cn_count').textContent=list.length+' record'+(list.length!==1?'s':''); const statusColor={Draft:'var(--muted)',Issued:'var(--green)',Cancelled:'var(--red)'}; document.getElementById('cn_tbody').innerHTML=list.map(c=>` ${c.cnNo||'โ€”'} ${c.date||'โ€”'} ${c.client||'โ€”'} ${c.refInvoice||'โ€”'} ${c.reason||'โ€”'} โ€” ${RM(c.amount||0)} ${c.status||'Draft'} ${c.authorizedBy||'โ€”'} `).join(''); } function openCNModal(id){ const cn=id?CN_LIST.find(c=>c.id===id):null; const today=new Date().toISOString().slice(0,10); const invOptions=(QUOT_LIST||[]).flatMap(q=>(q.invoices||[]).map(i=>i.invNo)).filter(Boolean).sort().reverse(); const clientOpts=[...new Set((QUOT_LIST||[]).map(q=>q.client).filter(Boolean))].sort(); document.getElementById('mt').textContent=cn?`Edit Credit Note โ€” ${cn.cnNo}`:'New Credit Note'; document.getElementById('md').style.maxWidth='700px'; document.getElementById('mb').innerHTML=`
${clientOpts.map(c=>`
${invOptions.map(i=>`
${cn?``:''}
`; document.getElementById('mo').classList.add('show'); } function saveCN(id){ const cnNo=document.getElementById('cn_no').value.trim(); const date=document.getElementById('cn_date').value; const client=document.getElementById('cn_client').value.trim(); const amount=parseFloat(document.getElementById('cn_amount').value)||0; const reason=document.getElementById('cn_reason').value.trim(); if(!date||!client||!reason){toast('Please fill Date, Client and Reason','var(--red)');return;} const data={ id:id||('CN'+Date.now()),cnNo,date,client,amount, refInvoice:document.getElementById('cn_refinv').value.trim(), reason, preparedBy:document.getElementById('cn_prepared').value.trim(), authorizedBy:document.getElementById('cn_auth').value.trim(), status:document.getElementById('cn_stat').value, remarks:document.getElementById('cn_remarks').value.trim(), }; if(id){const i=CN_LIST.findIndex(c=>c.id===id);if(i>=0)CN_LIST[i]=data;} else CN_LIST.unshift(data); saveCNs();closeModal();renderCNs(); toast('โœ… Credit Note saved'); } function deleteCN(id){ if(!confirm('Delete this Credit Note?'))return; CN_LIST=CN_LIST.filter(c=>c.id!==id);saveCNs();renderCNs();toast('Deleted'); } function printCN(id){ const cn=CN_LIST.find(c=>c.id===id);if(!cn)return; const f=v=>(+(v||0)).toLocaleString('en-MY',{minimumFractionDigits:2,maximumFractionDigits:2}); const w=window.open('','_blank');if(!w)return; w.document.write(` ${cn.cnNo} โ€“ Credit Note
${CO.name}
${CO.addr1}
${CO.addr2}
Tel: ${CO.phone} | Email: ${CO.email}

Credit Note

${cn.cnNo}
Date: ${cn.date}
${cn.status||'Draft'}
โš ๏ธ This credit note reduces the outstanding amount payable by the client indicated below.
Credit Details
Client${cn.client}
${cn.refInvoice?`
Reference Invoice${cn.refInvoice}
`:''}
Reason for Credit${cn.reason||'โ€”'}
${cn.remarks?`
Remarks${cn.remarks}
`:''}
CREDIT AMOUNT (MYR) RM ${f(cn.amount)}
In words: ${_numToWords(cn.amount||0)} Only
Prepared By
${cn.preparedBy||'___________________________'}
Signature / Date
Authorised By
${cn.authorizedBy||'___________________________'}
Signature / Date
`); w.document.close(); setTimeout(()=>w.print(),400); } function cnExportExcel(){ const rows=[['CN No','Date','Client','Ref Invoice','Reason','Amount (MYR)','Status','Prepared By','Authorised By','Remarks']]; CN_LIST.forEach(c=>rows.push([c.cnNo||'',c.date||'',c.client||'',c.refInvoice||'',c.reason||'',+(c.amount||0),c.status||'',c.preparedBy||'',c.authorizedBy||'',c.remarks||''])); _csvDownload(rows,'CreditNotes'); } function editLogoField(spanId,storageKey){ const span=document.getElementById(spanId);if(!span)return; const cur=span.textContent; const inp=document.createElement('input'); inp.value=cur; inp.style.cssText='background:var(--card2);border:1px solid var(--accent);border-radius:4px;padding:2px 6px;font-size:inherit;font-weight:inherit;font-family:inherit;color:inherit;outline:none;width:'+(Math.max(cur.length,6)*10)+'px;max-width:160px'; span.replaceWith(inp); inp.focus();inp.select(); const commit=()=>{ const val=inp.value.trim()||cur; const newSpan=document.createElement('span'); newSpan.id=spanId; newSpan.textContent=val; inp.replaceWith(newSpan); localStorage.setItem(storageKey,val); // Re-attach dblclick on parent newSpan.closest('[ondblclick],[title="Double-click to rename"]')?.addEventListener('dblclick',()=>editLogoField(spanId,storageKey)); }; inp.addEventListener('blur',commit); inp.addEventListener('keydown',e=>{if(e.key==='Enter')inp.blur();if(e.key==='Escape'){inp.value=cur;inp.blur();}}); } // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• // QUOTATION MODULE v2 โ€” INZ-QUO format // โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• const QUOT_PT={ 'Design Consultation (50%, 50%)':[ {pct:50,stage:'Deposit Upon Confirmation',desc:'Deposit of the total contract amount upon quotation agreed.'}, {pct:50,stage:'Completion of Project',desc:'Upon completion / practical handover.'} ], 'Design and Renovation (40%, 30%, 20%, 10%)':[ {pct:40,stage:'Deposit Upon Confirmation',desc:'Deposit of the total contract amount upon quotation agreed.'}, {pct:30,stage:'Completion Electricals and Plaster Ceiling Work',desc:'First progressive payment upon completion electrical and ceiling works.'}, {pct:20,stage:'On-site Installation of Carpentry Work',desc:'Second progressive payment upon on site installation of carpentry works.'}, {pct:10,stage:'Completion of Project',desc:'Upon Completion / Practical handover of work site.'} ] }; const QUOT_TC={ 'Terms & Conditions - Construction Use':`1. All cheque must be made payable to " INZII DESIGN STUDIO PLT "\n2. Valid for 30 days from date of quotation.\n3. Payment made are non-refundable, goods sold are non-exchangeable and non-returnable.\n4. You may conduct credit/trade check, CCRIS and DCEQS checks on me/us and where applicable with CTOS at any time for as long as I/We have a trade relationship with you or where any dues remain unpaid and outstanding with you, for any one or more of the following purposes:\n* Debt Recovery\n* Credit/Account Overview\n5. The project quotation, finalized 2D working drawing, 3D visual drawing and furniture detail drawing shall be acknowledged and signed by both the Client and the Company before the commencement of the renovation work. The costs from any modification request on the signed drawings would have to be borne by the Client.\n6. Cancellation of contract will lead to forfeit of payment.\n7. Any delay of the renovation timeline / handover date due to late of progress payment / change of design / late of confirmation / natural disaster / disease / or any forms that not done by us, we will not take any responsible on it.\n8. The 10% interior design service fee will be waived if construction work delivered by us upon final design confirmation.\n9. If client does not proceed with our design service, RM100 will be charged for mood board proposal.`, 'Default - Design Use':`1. All cheque must be made payable to " INZII DESIGN STUDIO PLT "\n2. Valid for 30 days from date of quotation.\n3. Payment made are non-refundable, goods sold are non-exchangeable and non-returnable.\n4. Design fee payment is non-refundable once the design process has commenced.\n5. All designs, drawings and materials prepared by INZII DESIGN STUDIO PLT remain the intellectual property of the company until full payment is received.\n6. Client is responsible for obtaining all necessary permits and approvals required for the project.\n7. INZII DESIGN STUDIO PLT reserves the right to use project images for portfolio and marketing purposes unless otherwise agreed in writing.` }; const QUOT_DA={ 'Design Agreement':`This Design Agreement ("Agreement") is entered into between INZII DESIGN STUDIO PLT (Reg No: 202004002372) ("Designer") and the Client named in this Quotation. SCOPE OF DESIGN SERVICES The Designer agrees to provide interior design services as outlined in the attached quotation, including concept design, 2D layout plan, 3D visualization and material/finish selection. DESIGN REVISIONS The Client is entitled to two (2) rounds of design revisions within the agreed scope. Any additional revisions or changes to the approved design direction will be subject to additional charges. DESIGN FEE & OWNERSHIP All design concepts, drawings, 3D renders and documentation produced by INZII DESIGN STUDIO PLT remain the intellectual property of the Designer until full payment is received. Upon full settlement, the finalized drawings shall be handed over to the Client. CLIENT OBLIGATIONS The Client agrees to provide timely feedback, approvals and all necessary information required to progress the design. Delays caused by the Client's late response shall not be the responsibility of the Designer. CONFIDENTIALITY Both parties agree to keep the terms of this Agreement and all design-related materials confidential and shall not disclose them to any third party without prior written consent. By signing this quotation, the Client acknowledges and agrees to the terms of this Design Agreement.`, 'Construction Agreement':`This Construction Agreement is entered into between INZII DESIGN STUDIO PLT (Reg No: 202004002372) ("Contractor") and the Client named in this Quotation. SCOPE OF WORKS Works shall be carried out as itemised in the attached quotation. Any variation works requested by the Client during the course of the project must be agreed upon in writing and may be subject to additional charges. SITE CONDITION & HANDOVER The Contractor shall exercise reasonable care during renovation works. The Client is responsible for removing or protecting personal property prior to commencement. Site handover is subject to final payment clearance. RENOVATION TIMELINE An estimated timeline will be provided upon confirmation. The Contractor shall not be held liable for delays caused by factors beyond reasonable control including but not limited to material supply delays, weather conditions, or changes requested by the Client. DEFECTS LIABILITY A defects liability period of fourteen (14) days from practical completion applies to workmanship defects. This does not cover damage caused by Client misuse or third-party interference. By signing this quotation, the Client acknowledges and agrees to the terms of this Construction Agreement.` }; const QUOT_UNITS=['JOB','NOS','SET','SQFT','FT','M','UNIT','PIECES','SF','LS','MM','CM','KG','ROLL','Mยฒ','Mยณ']; const QUOT_CO={name:'INZII DESIGN STUDIO PLT',reg:'202004002372',phone:'016-7365548',email:'info@inziidesign.com',address:'05-01, Jalan Molek 3/20,\nTaman Molek\nJohor Bahru\n81100, Johor',bankName:'Hong Leong Bank',bankAcc:'18100104774',bankAccName:'INZII DESIGN STUDIO PLT'}; const QUOT_STATUS2=['Draft','Sent','In Progress','Won','Completed','Cancelled']; const QUOT_SCOL={Draft:'var(--muted)',Sent:'var(--accent)','In Progress':'var(--yellow)',Won:'var(--green)',Completed:'var(--teal)',Cancelled:'var(--red)'}; let _qtForm=null; let _qtC=0; function _qid(){return 'q'+(++_qtC);} function quotNextNo(){ const maxN=QUOT_LIST.reduce((m,q)=>{const n=parseInt((q.quotNo||'INZ-QUO-00000').replace('INZ-QUO-',''));return Math.max(m,isNaN(n)?0:n);},328); return 'INZ-QUO-'+String(maxN+1).padStart(5,'0'); } function _qtNewItem(no){return{type:'item',id:_qid(),no:no||1,desc:'',desc2:'',qty:1,unit:'JOB',rate:0,cost:0,amount:0,foc:false,focRate:0};} function _qtNewSubHdr(){return{type:'subhdr',id:_qid(),title:''};} function _qtNewSection(opt){return{id:_qid(),title:'',optional:!!opt,items:[_qtNewItem(1)]};} const _QT_DEFAULT_SECTION_NAMES=['Masonry and Plumbing Work','Flooring Work','Plaster Ceiling & Partition Work','Aluminium and Glass Work','Carpentry Work','M&E Work','Air Cond Piping Work','Painting & Touch Up Work','Miscellaneous Work']; function _qtDefaultSections(){return _QT_DEFAULT_SECTION_NAMES.map(name=>({id:_qid(),title:name,optional:false,items:[_qtNewItem(1)]}));} // โ”€โ”€ Inventory โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function inventoryPage(){ return`
Item Name Category Unit Cost (MYR) Selling Price (MYR) Margin
`; } function renderInventory(){ const q=(document.getElementById('inv_search')?.value||'').toLowerCase(); const catF=document.getElementById('inv_cat')?.value||''; const unitF=document.getElementById('inv_unit')?.value||''; // Rebuild filter dropdowns const cats=[...new Set(INVENTORY.map(i=>i.category).filter(Boolean))].sort(); const units=[...new Set(INVENTORY.map(i=>i.unit).filter(Boolean))].sort(); const catEl=document.getElementById('inv_cat'); const unitEl=document.getElementById('inv_unit'); if(catEl){const v=catEl.value;catEl.innerHTML=''+cats.map(c=>`${c}`).join('');} if(unitEl){const v=unitEl.value;unitEl.innerHTML=''+units.map(u=>`${u}`).join('');} // Also update datalist in modal const dl=document.getElementById('inv_cat_list'); if(dl)dl.innerHTML=cats.map(c=>``).join(''); const isFoc=!!it.foc; const _iAmt=isFoc?0:(it.qty||0)*(it.rate||0);const _iCost=(it.qty||0)*+(it.cost||0);const _iProfit=_iAmt-_iCost;const _iPct=_iAmt>0?(_iProfit/_iAmt*100):0; return`
โ ฟ
${it.no} ${isFoc?'':`
Profit: ${_iProfit.toLocaleString('en-MY',{minimumFractionDigits:2})} (${_iPct.toFixed(2)}%)
`} ${isFoc ? `
FOC
${it.focRate?`
MYR ${((it.qty||1)*(it.focRate||0)).toFixed(2)}
`:''} ` : `
MYR ${((it.qty||0)*(it.rate||0)).toFixed(2)}
`}
= MYR ${((it.qty||0)*(it.cost||0)).toLocaleString('en-MY',{minimumFractionDigits:2})}
`; } function qtToggleFoc(sid,iid){ const sec=_qtForm.sections.find(s=>s.id===sid);if(!sec)return; const it=sec.items.find(i=>i.id===iid);if(!it)return; it.foc=!it.foc; if(it.foc){it.focRate=it.rate||0;it.rate=0;} else{it.rate=it.focRate||0;it.focRate=0;} qtRenderSections(); } function qtAddSection(opt){_qtForm.sections.push(_qtNewSection(opt));qtRenderSections();} function qtApplyTemplate(){ const sel=document.getElementById('qt_tpl_sel'); const name=sel?.value; if(!name){toast('Please select a template first','var(--red)');return;} const tpl=(QUOT_SETTINGS.quotTemplates||{})[name]; if(!tpl||!tpl.length){toast('Template is empty','var(--muted)');return;} const hasSections=(_qtForm.sections||[]).some(s=>s.items?.some(i=>i.desc||i.qty)); if(hasSections&&!confirm('Apply "'+name+'" template? This will replace existing sections.')){return;} _qtForm.sections=tpl.map((s,si)=>{ const sec={..._qtNewSection(s.optional),title:s.title,optional:!!s.optional}; if(s.items&&s.items.length){ sec.items=s.items.map((item,ii)=>{ const it=_qtNewItem(ii+1); it.desc=item.desc||''; it.desc2=item.desc2||''; it.unit=item.unit||'JOB'; return it; }); } return sec; }); qtRenderSections(); toast('Template "'+name+'" applied โœ“','var(--green)'); sel.value=''; } function qtRemoveSection(sid){if(_qtForm.sections.length<=1)return;_qtForm.sections=_qtForm.sections.filter(s=>s.id!==sid);qtRenderSections();} function qtAddItem(sid){ const sec=_qtForm.sections.find(s=>s.id===sid);if(!sec)return; const gmax=_qtForm.sections.reduce((m,s)=>s.items.reduce((mm,it)=>it.type==='item'?Math.max(mm,it.no||0):m,m),0); sec.items.push(_qtNewItem(gmax+1)); qtRenderSections(); } function qtAddSubHdr(sid){ const sec=_qtForm.sections.find(s=>s.id===sid);if(!sec)return; sec.items.push(_qtNewSubHdr()); qtRenderSections(); } function qtInsertSubHdr(sid,iid){ // Insert sub-section header BEFORE the item with id=iid const sec=_qtForm.sections.find(s=>s.id===sid);if(!sec)return; const ii=sec.items.findIndex(it=>it.id===iid); if(ii<0){sec.items.push(_qtNewSubHdr());} else{sec.items.splice(ii,0,_qtNewSubHdr());} qtRenderSections(); } function qtInsertItem(sid,iid){ // Insert new item AFTER the item with id=iid const sec=_qtForm.sections.find(s=>s.id===sid);if(!sec)return; const ii=sec.items.findIndex(it=>it.id===iid); const gmax=_qtForm.sections.reduce((m,s)=>s.items.reduce((mm,it)=>it.type==='item'?Math.max(mm,it.no||0):mm,m),0); const newItem=_qtNewItem(gmax+1); if(ii<0){sec.items.push(newItem);} else{sec.items.splice(ii+1,0,newItem);} _qtRenum();qtRenderSections(); } // โ”€โ”€ Drag-and-drop โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ let _qtDragFrom=null,_qtDragTr=null; function _qtDragStart(e,secId,itemId){ _qtDragFrom={secId,itemId}; _qtDragTr=e.currentTarget.closest('tr'); if(_qtDragTr)_qtDragTr.classList.add('qt-dragging'); e.dataTransfer.effectAllowed='move'; e.dataTransfer.setData('text/plain',itemId); } function _qtDragEnd(){ if(_qtDragTr){_qtDragTr.classList.remove('qt-dragging');_qtDragTr=null;} document.querySelectorAll('.qt-drop-before,.qt-drop-after').forEach(el=>{el.classList.remove('qt-drop-before','qt-drop-after');}); } function _qtDragOver(e,tr,secId,itemId){ e.preventDefault(); e.dataTransfer.dropEffect='move'; document.querySelectorAll('.qt-drop-before,.qt-drop-after').forEach(el=>{el.classList.remove('qt-drop-before','qt-drop-after');}); if(!_qtDragFrom||_qtDragFrom.itemId===itemId)return; const rect=tr.getBoundingClientRect(); tr.classList.add(e.clientYs.id===fromSecId); const fromIdx=fromSec.items.findIndex(it=>it.id===fromItemId); if(fromIdx<0)return; const[item]=fromSec.items.splice(fromIdx,1); if(fromSec.items.filter(i=>i.type==='item').length===0)fromSec.items.push(_qtNewItem(1)); // Insert into target const toSec=_qtForm.sections.find(s=>s.id===targetSecId); let toIdx=toSec.items.findIndex(it=>it.id===targetItemId); if(fromSecId===targetSecId&&fromIdx<=toIdx)toIdx--; const tr=document.getElementById('qtrow_'+targetItemId); const rect=tr?tr.getBoundingClientRect():null; const before=rect&&e.clientYs.id===fromSecId); const fromIdx=fromSec.items.findIndex(it=>it.id===fromItemId); if(fromIdx<0)return; const[item]=fromSec.items.splice(fromIdx,1); if(fromSec.items.filter(i=>i.type==='item').length===0)fromSec.items.push(_qtNewItem(1)); const toSec=_qtForm.sections.find(s=>s.id===targetSecId); toSec.items.push(item); _qtRenum();qtRenderSections(); } function qtMoveSection(sid,dir){ const i=_qtForm.sections.findIndex(s=>s.id===sid);if(i<0)return; const j=i+dir;if(j<0||j>=_qtForm.sections.length)return; [_qtForm.sections[i],_qtForm.sections[j]]=[_qtForm.sections[j],_qtForm.sections[i]]; qtRenderSections(); } function qtMoveItem(sid,iid,dir){ const si=_qtForm.sections.findIndex(s=>s.id===sid);if(si<0)return; const sec=_qtForm.sections[si]; const ii=sec.items.findIndex(it=>it.id===iid);if(ii<0)return; const jj=ii+dir; if(jj>=0&&jj0){ // Cross up โ†’ end of previous section const prevSec=_qtForm.sections[si-1]; const[item]=sec.items.splice(ii,1); if(sec.items.filter(i=>i.type==='item').length===0)sec.items.push(_qtNewItem(1)); prevSec.items.push(item); } else if(dir>0&&si<_qtForm.sections.length-1){ // Cross down โ†’ start of next section const nextSec=_qtForm.sections[si+1]; const[item]=sec.items.splice(ii,1); if(sec.items.filter(i=>i.type==='item').length===0)sec.items.push(_qtNewItem(1)); nextSec.items.unshift(item); } else { return; // absolute boundary } _qtRenum();qtRenderSections(); } function qtRemoveItem(sid,iid){ const sec=_qtForm.sections.find(s=>s.id===sid);if(!sec)return; const realItems=sec.items.filter(it=>it.type==='item'); if(realItems.length<=1&&sec.items.find(it=>it.id===iid)?.type==='item')return; sec.items=sec.items.filter(it=>it.id!==iid); _qtRenum();qtRenderSections(); } function _qtRenum(){let n=1;(_qtForm.sections||[]).forEach(s=>s.items.forEach(it=>{if(it.type==='item')it.no=n++;}));} // โ”€โ”€ Inventory Autocomplete in Quotation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ let _invAcTimer=null; function _invAcShow(secId,iid,input){ clearTimeout(_invAcTimer); const q=(input.value||'').toLowerCase().trim(); const drop=document.getElementById('invac_drop_'+iid); if(!drop)return; if(!q||!INVENTORY.length){drop.style.display='none';return;} const matches=INVENTORY.filter(i=>i.name.toLowerCase().includes(q)).slice(0,10); if(!matches.length){drop.style.display='none';return;} drop.innerHTML=matches.map(i=>`
${i.name} MYR ${(+i.price||0).toFixed(2)}
${i.category?`${i.category}`:''}${i.unit}
`).join(''); drop.style.display='block'; } function _invAcHide(iid){ _invAcTimer=setTimeout(()=>{ const d=document.getElementById('invac_drop_'+iid); if(d)d.style.display='none'; },150); } function _invAcSelect(secId,iid,invId){ const inv=INVENTORY.find(i=>i.id===invId); if(!inv)return; // Fill item fields _qti(secId,iid,'desc',inv.name); _qtin(secId,iid,'rate',inv.price); _qtin(secId,iid,'cost',inv.cost); _qti(secId,iid,'unit',inv.unit); // Update DOM inputs const nameEl=document.getElementById('invac_'+iid); if(nameEl)nameEl.value=inv.name; // Find row and update rate, cost, unit selects const row=document.getElementById('qtrow_'+iid); if(row){ const inputs=row.querySelectorAll('input[type="number"]'); // rate input (index 1 = qty, 2 = rate, 3 = cost based on order in _qtItemRow) const allNum=row.querySelectorAll('input[type="number"],select'); // Update via re-render to be safe } // Re-render sections to sync all fields _qtRenum();qtRenderSections(); // Restore cursor to name field after re-render setTimeout(()=>{ const el=document.getElementById('invac_'+iid); if(el){el.focus();el.setSelectionRange(el.value.length,el.value.length);} },50); } // ID-based setters โ€” safe across drag/reorder function _qts(sid,field,val){const s=_qtForm.sections.find(x=>x.id===sid);if(s)s[field]=val;} function _qti(sid,iid,field,val){const s=_qtForm.sections.find(x=>x.id===sid);if(!s)return;const it=s.items.find(x=>x.id===iid);if(it)it[field]=val;} function _qtin(sid,iid,field,val){const s=_qtForm.sections.find(x=>x.id===sid);if(!s)return;const it=s.items.find(x=>x.id===iid);if(!it)return;it[field]=+val;qtCalcTotals();} function qtCalcTotals(){ let grand=0,totalCost=0; (_qtForm.sections||[]).forEach(sec=>{ const _excl=/^(omission|discount)$/i.test((sec.title||'').trim()); let secT=0; sec.items.forEach((it,ii)=>{ if(it.type==='subhdr')return; if(it.foc){it.amount=0;return;} const amt=(it.qty||0)*(it.rate||0); const costAmt=(it.qty||0)*+(it.cost||0); it.amount=amt; if(!sec.optional&&!_excl){secT+=amt;totalCost+=costAmt;} const el=document.getElementById('qtamt_'+it.id); if(el)el.textContent='MYR '+amt.toFixed(2); const ce=document.getElementById('qtcost_'+it.id); if(ce)ce.textContent='= MYR '+costAmt.toLocaleString('en-MY',{minimumFractionDigits:2}); const pe=document.getElementById('qtprofit_'+it.id); if(pe){const ip=amt-costAmt;const ipPct=amt>0?(ip/amt*100):0;pe.textContent='Profit: '+ip.toLocaleString('en-MY',{minimumFractionDigits:2})+' ('+ipPct.toFixed(2)+'%)';pe.style.color=ip>=0?'var(--green)':'var(--red)';} }); if(!sec.optional&&!_excl)grand+=secT; const se=document.getElementById('qsectot_'+sec.id); if(se)se.textContent='MYR '+(sec.items.reduce((s,it)=>s+(it.amount||0),0)).toFixed(2); }); const disc=+(document.getElementById('qtf_disc')?.value||0); const tax=+(document.getElementById('qtf_tax')?.value||0); const final=Math.max(0,grand-disc+tax); const profit=final-totalCost; _qtForm.totalAmt=grand;_qtForm.totalDisc=disc;_qtForm.taxAmt=tax;_qtForm.finalAmt=final;_qtForm.totalCost=totalCost;_qtForm.profit=profit; const ta=document.getElementById('qt_tot_amt');const fa=document.getElementById('qt_final_amt'); const tc=document.getElementById('qt_tot_cost');const tp=document.getElementById('qt_profit');const fr=document.getElementById('qt_final_ref'); if(ta)ta.textContent='MYR '+grand.toLocaleString('en-MY',{minimumFractionDigits:2}); if(fa)fa.textContent='MYR '+final.toLocaleString('en-MY',{minimumFractionDigits:2}); if(fr)fr.textContent='MYR '+final.toLocaleString('en-MY',{minimumFractionDigits:2}); if(tc)tc.textContent='MYR '+totalCost.toLocaleString('en-MY',{minimumFractionDigits:2}); if(tp){tp.textContent='MYR '+profit.toLocaleString('en-MY',{minimumFractionDigits:2});tp.style.color=profit>=0?'var(--green)':'var(--red)';} const pp=document.getElementById('qt_profit_pct'); if(pp){const pct=final>0?(profit/final*100):0;pp.textContent=pct.toFixed(1)+' %';pp.style.color=pct>=0?'var(--green)':'var(--red)';} } function saveQuotForm(){ _qtForm.client=document.getElementById('qtf_client')?.value.trim()||''; _qtForm.clientPhone=document.getElementById('qtf_phone')?.value.trim()||''; _qtForm.remarks=document.getElementById('qtf_remarks')?.value.trim()||''; const newId=(document.getElementById('qtf_id')?.value.trim()||'').toUpperCase(); if(newId&&newId!==_qtForm.id){QUOT_LIST=QUOT_LIST.filter(x=>x.id!==_qtForm.id);_qtForm.id=newId;_qtForm.quotNo=newId.replace(/-R\d+$/i,'');} _qtForm.date=document.getElementById('qtf_date')?.value||''; _qtForm.tag=document.getElementById('qtf_tag')?.value.trim()||''; _qtForm.handler=document.getElementById('qtf_handler')?.value.trim()||'Inzii Design'; _qtForm.status=document.getElementById('qtf_status')?.value||'Draft'; _qtForm.wonDeal=document.getElementById('qtf_won')?.value||''; _qtForm.quotType=document.getElementById('qtf_qtype')?.value||''; _qtForm.paymentTerm=document.getElementById('qtf_pt')?.value||''; _qtForm.termCondition=document.getElementById('qtf_tc')?.value||''; _qtForm.designAgreement=document.getElementById('qtf_da')?.value||''; _qtRenum(); qtCalcTotals(); _qtForm.updatedAt=new Date().toISOString(); const idx=QUOT_LIST.findIndex(x=>x.id===_qtForm.id); if(idx>=0)QUOT_LIST[idx]={..._qtForm,sections:JSON.parse(JSON.stringify(_qtForm.sections))}; else QUOT_LIST.push({..._qtForm,sections:JSON.parse(JSON.stringify(_qtForm.sections))}); saveQuotations(); toast('Saved โœ“','var(--green)'); } function qtNewRevision(){ saveQuotForm(); const newRev={...JSON.parse(JSON.stringify(_qtForm))}; newRev.revision=_qtForm.revision+1; newRev.id=_qtForm.quotNo+'-R'+newRev.revision; newRev.createdAt=new Date().toISOString(); newRev.updatedAt=new Date().toISOString(); QUOT_LIST.push(newRev); saveQuotations(); _qtForm=newRev; _qtFixIds(_qtForm); toast('New Revision R'+newRev.revision+' created','var(--green)'); document.getElementById('content').innerHTML=_qtFormHTML(); qtRenderSections(); } function deleteQuot(id){ if(!confirm('Delete quotation '+id+'?'))return; QUOT_LIST=QUOT_LIST.filter(x=>x.id!==id); saveQuotations();renderQuotations(); } function duplicateQuot(id){ const src=QUOT_LIST.find(x=>x.id===id); if(!src)return; const newNo=quotNextNo(); const copy=JSON.parse(JSON.stringify(src)); copy.id=newNo+'-R0'; copy.quotNo=newNo; copy.revision=0; copy.status='Draft'; copy.wonDeal=''; copy.pis=[]; copy.createdAt=new Date().toISOString(); copy.updatedAt=new Date().toISOString(); copy.date=new Date().toISOString().slice(0,10); // Assign new IDs to all sections and items copy.sections=(copy.sections||[]).map(s=>({ ...s,id:_qid(), items:s.items.map(it=>({...it,id:_qid()})) })); QUOT_LIST.push(copy); saveQuotations(); renderQuotations(); toast('Duplicated as '+copy.id+' โœ“','var(--teal)'); } // โ”€โ”€ PDF Print โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ function printQuotation(id){ const q=id?QUOT_LIST.find(x=>x.id===id):_qtForm; if(!q){toast('Quotation not found','var(--red)');return;} // Always recalculate amounts and renumber โ€” ensures PDF is always correct regardless of stored state let _pdfN=1; (q.sections||[]).forEach(sec=>sec.items.forEach(it=>{ if(it.type==='item'){it.no=_pdfN++;it.amount=it.foc?0:(+(it.qty)||0)*(+(it.rate)||0);} })); const fmtD=d=>{if(!d)return'โ€”';const[y,m,dy]=d.split('-');return`${dy}-${m}-${y}`;}; const fmtA=n=>`MYR ${(+n||0).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g,',')}`; const _secHasContent=sec=>sec.items.some(it=>it.type==='subhdr'?(it.title||'').trim():((it.desc||'').trim()||+it.amount)); const mainSec=(q.sections||[]).filter(s=>!s.optional); const optSec=(q.sections||[]).filter(s=>s.optional); const pt=QUOT_PT[q.paymentTerm]||QUOT_SETTINGS?.paymentTerms?.[q.paymentTerm]||[]; const tc=QUOT_TC[q.termCondition]||QUOT_SETTINGS?.termsConditions?.[q.termCondition]||''; const docHdr=`${q.id} - ${QUOT_CO.name}`; const css=`@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;1,300&display=swap'); *{margin:0;padding:0;box-sizing:border-box;} body{font-family:'DM Sans',Arial,sans-serif;font-weight:300;font-size:10.5px;color:#231f20;background:#f6f3ee;} @page{margin:0;size:A4;} html,body{background:#f6f3ee;} .cover{padding:14mm 14mm;min-height:297mm;background:#f6f3ee;box-sizing:border-box;page-break-after:always;} .sections{padding:10mm 14mm;min-height:297mm;background:#f6f3ee;box-sizing:border-box;} .footer-pg{padding:14mm 14mm;min-height:297mm;display:flex;flex-direction:column;box-sizing:border-box;background:#f6f3ee;page-break-before:always;} .dh{text-align:center;font-size:8px;color:#9a8f85;margin-bottom:8mm;letter-spacing:2px;text-transform:uppercase;} h1.qt{font-family:'Cormorant Garamond',Georgia,serif;font-size:30px;letter-spacing:10px;text-align:right;font-weight:300;color:#231f20;margin-bottom:10mm;text-transform:uppercase;} .logo{font-family:'Cormorant Garamond',Georgia,serif;font-size:20px;font-weight:300;color:#231f20;letter-spacing:4px;margin-bottom:16mm;} .logo-sub{font-size:8px;letter-spacing:3px;text-transform:uppercase;color:#9a8f85;margin-top:2px;} .infotbl{width:100%;border-collapse:collapse;margin-bottom:7mm;} .infotbl td{padding:5px 8px;font-size:10px;border-bottom:1px solid #ddd8cf;} .infotbl td.lbl{color:#9a8f85;width:110px;letter-spacing:.5px;}.infotbl td.val{font-weight:500;} .box{border:1px solid #ddd8cf;overflow:hidden;margin-bottom:6mm;page-break-inside:avoid;} .bh{background:#f6f3ee;padding:7px 10px;font-weight:500;font-size:10.5px;border-bottom:1px solid #ddd8cf;letter-spacing:.5px;color:#3c2415;} table.it{width:100%;border-collapse:collapse;} table.it th{background:#231f20;color:#fff;padding:7px 9px;font-size:9.5px;text-align:left;font-weight:400;letter-spacing:1px;text-transform:uppercase;} table.it th.r,table.it td.r{text-align:right;} table.it td{padding:7px 9px;font-size:10px;border-bottom:1px solid #ddd8cf;vertical-align:top;} table.it tr:nth-child(even) td{background:#f6f3ee;} .stot{text-align:right;font-weight:600;font-size:11px;padding:6px 9px;border-top:1px solid #ddd8cf;color:#3c2415;} .footer2col{display:grid;grid-template-columns:1fr 1fr;gap:18mm;margin-bottom:8mm;font-size:9.5px;line-height:1.9;} .pt-tbl{width:100%;border-collapse:collapse;margin-bottom:6mm;} .pt-tbl th{background:#231f20;color:#fff;padding:6px 9px;font-size:9px;text-align:left;font-weight:400;letter-spacing:1px;text-transform:uppercase;} .pt-tbl td{padding:5px 9px;font-size:9.5px;border-bottom:1px solid #ddd8cf;} .tc{font-size:9px;line-height:1.9;color:#6b6260;margin-bottom:6mm;} .tc ol,.tc ul{padding-left:18px;margin:3px 0;} .tc li{margin-bottom:2px;} .tc h3{font-size:10px;font-weight:600;margin:6px 0 3px;color:#231f20;letter-spacing:.5px;} .tc div{margin:1px 0;} .sig{display:grid;grid-template-columns:1fr 1fr;gap:20mm;margin-top:8mm;} @media print{html,body{print-color-adjust:exact;-webkit-print-color-adjust:exact;background:#f6f3ee;}}`; // Cover page const sumRows=mainSec.filter(_secHasContent).map(s=>{const t=s.items.filter(i=>i.type==='item').reduce((a,it)=>a+(it.amount||0),0);return`${s.title||'โ€”'}${fmtA(t)}`;}).join(''); const optRows=optSec.filter(_secHasContent).map(s=>{const t=s.items.filter(i=>i.type==='item').reduce((a,it)=>a+(it.amount||0),0);return`${s.title||'Optional Item'}${fmtA(t)}`;}).join(''); const optGrand=optSec.reduce((a,s)=>a+s.items.filter(i=>i.type==='item').reduce((b,it)=>b+(it.amount||0),0),0); const _logoSrc2=QUOT_SETTINGS.logo||'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNzggNDgiIGZpbGw9Im5vbmUiPjxnIHN0cm9rZT0iIzIzMWYyMCIgc3Ryb2tlLXdpZHRoPSIxLjYiIHN0cm9rZS1saW5lY2FwPSJzcXVhcmUiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiPjxsaW5lIHgxPSI1IiB5MT0iMyIgeDI9IjUiIHkyPSI0NSIvPjxsaW5lIHgxPSIyMiIgeTE9IjMiIHgyPSIyMiIgeTI9IjQ1Ii8+PGxpbmUgeDE9IjIyIiB5MT0iMyIgeDI9IjQwIiB5Mj0iNDUiLz48bGluZSB4MT0iNDAiIHkxPSIzIiB4Mj0iNDAiIHkyPSI0NSIvPjxsaW5lIHgxPSI1NCIgeTE9IjMiIHgyPSI3MiIgeTI9IjMiLz48bGluZSB4MT0iNzIiIHkxPSIzIiB4Mj0iNTQiIHkyPSI0NSIvPjxsaW5lIHgxPSI1NCIgeTE9IjQ1IiB4Mj0iNzIiIHkyPSI0NSIvPjxsaW5lIHgxPSI4NiIgeTE9IjMiIHgyPSI4NiIgeTI9IjQ1Ii8+PGxpbmUgeDE9IjEwMyIgeTE9IjMiIHgyPSIxMDMiIHkyPSI0NSIvPjwvZz48L3N2Zz4='; const logoHtml=``; const co2=QUOT_SETTINGS.company||QUOT_CO; let pages=`
${logoHtml}

Q U O T A T I O N

${co2.name||''}
(Reg No : ${co2.reg||''})
${co2.address||''}
Attention To:${(q.client||'โ€”').replace(/
${q.clientPhone?`
Tel:${q.clientPhone}
`:''} ${q.remarks?`
Project Title:${q.remarks.replace(/
`:''} ${q.tag?`
Project Site:${q.tag.replace(/
`:''}
Quotation No.:${q.id}
Issue Date:${fmtD(q.date)}
Valid Until:${q.date?(()=>{const d=new Date(q.date);d.setDate(d.getDate()+30);return fmtD(d.toISOString().split('T')[0]);})():'โ€”'}
Designer:${q.handler||'Inzii Design'}
Summary of Works ${q.paymentTerm||''}
${sumRows} ${q.totalDisc?``:''} ${q.taxAmt?``:''}
Section / DescriptionAmount (MYR)
Subtotal ${fmtA(q.totalAmt)}
Discount- ${fmtA(q.totalDisc)}
Tax (SST)${fmtA(q.taxAmt)}
GRAND TOTAL MYR ${(+(q.finalAmt)||0).toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g,',')}
${optRows?`
Optional Items (Not Included in Grand Total)
${optRows}
DescriptionAmount (MYR)
Optional Total${fmtA(optGrand)}
`:''}
This quotation is valid for 30 days from the issue date ยท ${co2.name||''} ยท ${co2.phone||''} ยท ${co2.email||''}
`; // All sections โ€” continuous flow, no forced page breaks between them const secBlocks=[...mainSec,...optSec].filter(_secHasContent).map(sec=>{ const rows=sec.items.map(it=>{ if(it.type==='subhdr'){ return`${(it.title||'').replace(/`; } return` ${it.no}
${(it.desc||'โ€”').replace(/ ${it.desc2?`
${it.desc2.replace(/`:''} ${it.qty} ${it.unit||''} ${it.foc?(it.focRate?`MYR ${(it.focRate||0).toFixed(2)}`:'โ€”'):'MYR '+(it.rate||0).toFixed(2)} ${it.foc?'FOC':'MYR '+(it.amount||0).toFixed(2)} `; }).join(''); const secT=sec.items.filter(i=>i.type==='item').reduce((a,it)=>a+(it.amount||0),0); return`
${sec.optional?'[Optional]':''}${sec.title||'Section'}
${rows}
NoItemQtyUnitRate (MYR)Amount (MYR)
Section Total: ${fmtA(secT)}
`; }).join(''); pages+=`
${secBlocks}
`; // โ”€โ”€ Single combined footer page: Company + Bank + PT + T&C + Agreement + Signature โ”€โ”€ const ptRows=pt.map(p=>`${p.pct}%${p.stage}${p.desc}`).join(''); const signer=QUOT_SETTINGS.signer||{name:'Kavyn Liew',title:'Director',nric:'920328-01-5997'}; const co=QUOT_CO; const da=QUOT_DA[q.designAgreement]||(QUOT_SETTINGS?.designAgreements?.[q.designAgreement])||''; const sigImg=QUOT_SETTINGS.sigImage?``:`
`; pages+=`