[{"data":1,"prerenderedAt":465},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fadministration\u002Fbackups-and-updates":159,"\u002Fdocs\u002Fadministration\u002Fbackups-and-updates-surround":460},[4,28,54,85,115,145],{"title":5,"path":6,"stem":7,"children":8,"icon":27},"Getting started","\u002Fdocs\u002Fgetting-started","1.docs\u002F1.getting-started\u002F1.index",[9,12,17,22],{"title":10,"path":6,"stem":7,"icon":11},"What SecureOps is","i-lucide-book-open",{"title":13,"path":14,"stem":15,"icon":16},"Signing in","\u002Fdocs\u002Fgetting-started\u002Fsigning-in","1.docs\u002F1.getting-started\u002F2.signing-in","i-lucide-log-in",{"title":18,"path":19,"stem":20,"icon":21},"Finding your way","\u002Fdocs\u002Fgetting-started\u002Ffinding-your-way","1.docs\u002F1.getting-started\u002F3.finding-your-way","i-lucide-compass",{"title":23,"path":24,"stem":25,"icon":26},"Roles and what each sees","\u002Fdocs\u002Fgetting-started\u002Froles","1.docs\u002F1.getting-started\u002F4.roles","i-lucide-users","i-lucide-rocket",{"title":29,"icon":30,"path":31,"stem":32,"children":33,"page":53},"Selling","i-lucide-scan-barcode","\u002Fdocs\u002Fselling","1.docs\u002F2.selling",[34,38,43,48],{"title":35,"path":36,"stem":37,"icon":30},"The till","\u002Fdocs\u002Fselling\u002Fthe-till","1.docs\u002F2.selling\u002F1.the-till",{"title":39,"path":40,"stem":41,"icon":42},"Receipts","\u002Fdocs\u002Fselling\u002Freceipts","1.docs\u002F2.selling\u002F2.receipts","i-lucide-receipt",{"title":44,"path":45,"stem":46,"icon":47},"Sales by day","\u002Fdocs\u002Fselling\u002Fsales-by-day","1.docs\u002F2.selling\u002F3.sales-by-day","i-lucide-calendar-days",{"title":49,"path":50,"stem":51,"icon":52},"Closing the day","\u002Fdocs\u002Fselling\u002Fclosing-the-day","1.docs\u002F2.selling\u002F4.closing-the-day","i-lucide-send",false,{"title":55,"icon":56,"path":57,"stem":58,"children":59,"page":53},"Stock","i-lucide-boxes","\u002Fdocs\u002Fstock","1.docs\u002F3.stock",[60,65,70,75,80],{"title":61,"path":62,"stem":63,"icon":64},"Products","\u002Fdocs\u002Fstock\u002Fproducts","1.docs\u002F3.stock\u002F1.products","i-lucide-pill",{"title":66,"path":67,"stem":68,"icon":69},"The FDA register","\u002Fdocs\u002Fstock\u002Fthe-fda-register","1.docs\u002F3.stock\u002F2.the-fda-register","i-lucide-badge-check",{"title":71,"path":72,"stem":73,"icon":74},"Purchases and deliveries","\u002Fdocs\u002Fstock\u002Fpurchases-and-deliveries","1.docs\u002F3.stock\u002F3.purchases-and-deliveries","i-lucide-truck",{"title":76,"path":77,"stem":78,"icon":79},"Expiry and quarantine","\u002Fdocs\u002Fstock\u002Fexpiry-and-quarantine","1.docs\u002F3.stock\u002F4.expiry-and-quarantine","i-lucide-calendar-clock",{"title":81,"path":82,"stem":83,"icon":84},"Disposals","\u002Fdocs\u002Fstock\u002Fdisposals","1.docs\u002F3.stock\u002F5.disposals","i-lucide-flame",{"title":86,"icon":87,"path":88,"stem":89,"children":90,"page":53},"Compliance","i-lucide-shield-check","\u002Fdocs\u002Fcompliance","1.docs\u002F4.compliance",[91,95,100,105,110],{"title":92,"path":93,"stem":94,"icon":69},"The licence and the shop","\u002Fdocs\u002Fcompliance\u002Flicence-and-shop","1.docs\u002F4.compliance\u002F1.licence-and-shop",{"title":96,"path":97,"stem":98,"icon":99},"Reminders","\u002Fdocs\u002Fcompliance\u002Freminders","1.docs\u002F4.compliance\u002F2.reminders","i-lucide-bell",{"title":101,"path":102,"stem":103,"icon":104},"Reports and exports","\u002Fdocs\u002Fcompliance\u002Freports-and-exports","1.docs\u002F4.compliance\u002F3.reports-and-exports","i-lucide-file-spreadsheet",{"title":106,"path":107,"stem":108,"icon":109},"Sales summaries","\u002Fdocs\u002Fcompliance\u002Fsales-summaries","1.docs\u002F4.compliance\u002F4.sales-summaries","i-lucide-chart-column",{"title":111,"path":112,"stem":113,"icon":114},"The audit trail","\u002Fdocs\u002Fcompliance\u002Faudit-trail","1.docs\u002F4.compliance\u002F5.audit-trail","i-lucide-scroll-text",{"title":116,"icon":117,"path":118,"stem":119,"children":120,"page":53},"Administration","i-lucide-settings-2","\u002Fdocs\u002Fadministration","1.docs\u002F5.administration",[121,125,130,135,140],{"title":122,"path":123,"stem":124,"icon":26},"Users and roles","\u002Fdocs\u002Fadministration\u002Fusers-and-roles","1.docs\u002F5.administration\u002F1.users-and-roles",{"title":126,"path":127,"stem":128,"icon":129},"The shop PC","\u002Fdocs\u002Fadministration\u002Fthe-shop-pc","1.docs\u002F5.administration\u002F2.the-shop-pc","i-lucide-monitor",{"title":131,"path":132,"stem":133,"icon":134},"Install as an app","\u002Fdocs\u002Fadministration\u002Finstall-as-an-app","1.docs\u002F5.administration\u002F3.install-as-an-app","i-lucide-smartphone",{"title":136,"path":137,"stem":138,"icon":139},"Mail and text messages","\u002Fdocs\u002Fadministration\u002Fmail-and-sms","1.docs\u002F5.administration\u002F4.mail-and-sms","i-lucide-mail",{"title":141,"path":142,"stem":143,"icon":144},"Backups and updates","\u002Fdocs\u002Fadministration\u002Fbackups-and-updates","1.docs\u002F5.administration\u002F5.backups-and-updates","i-lucide-database-backup",{"title":146,"icon":147,"path":148,"stem":149,"children":150,"page":53},"Regulation","i-lucide-scale","\u002Fdocs\u002Fregulation","1.docs\u002F6.regulation",[151,155],{"title":152,"path":153,"stem":154,"icon":87},"What an OTCMS may sell","\u002Fdocs\u002Fregulation\u002Fwhat-the-shop-may-sell","1.docs\u002F6.regulation\u002F1.what-the-shop-may-sell",{"title":156,"path":157,"stem":158,"icon":114},"The records the law wants","\u002Fdocs\u002Fregulation\u002Fthe-records-the-law-wants","1.docs\u002F6.regulation\u002F2.the-records-the-law-wants",{"id":160,"title":141,"body":161,"description":453,"extension":454,"links":455,"meta":456,"navigation":457,"path":142,"seo":458,"stem":143,"__hash__":459},"docs\u002F1.docs\u002F5.administration\u002F5.backups-and-updates.md",{"type":162,"value":163,"toc":447},"minimark",[164,169,183,214,221,274,288,292,295,358,361,365,372,436,440,443],[165,166,168],"h2",{"id":167},"backups-every-night","Backups, every night",[170,171,172,173,177,178,182],"p",{},"A scheduled task dumps the whole database into the ",[174,175,176],"code",{},"backups\u002F"," folder inside the system's folder, keeps thirty days of dumps, and copies the newest to the ",[179,180,181],"strong",{},"backup copy"," location: a USB drive that stays plugged in, or a folder on another machine.",[184,185,190],"pre",{"className":186,"code":187,"language":188,"meta":189,"style":189},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","docker compose run --rm otcms-backup\n","bash","",[174,191,192],{"__ignoreMap":189},[193,194,197,201,205,208,211],"span",{"class":195,"line":196},"line",1,[193,198,200],{"class":199},"sBMFI","docker",[193,202,204],{"class":203},"sfazB"," compose",[193,206,207],{"class":203}," run",[193,209,210],{"class":203}," --rm",[193,212,213],{"class":203}," otcms-backup\n",[170,215,216,217,220],{},"It is scheduled at install: on Linux with ",[174,218,219],{},"cron"," at 22:15, on Windows with Task Scheduler. The line the scheduler runs, so it can be checked:",[184,222,224],{"className":186,"code":223,"language":188,"meta":189,"style":189},"15 22 * * * cd \u002Fhome\u002Fshop\u002Fotcms && docker compose run --rm otcms-backup >> backups\u002Fbackup.log 2>&1\n",[174,225,226],{"__ignoreMap":189},[193,227,228,231,235,239,241,243,246,249,253,256,258,260,262,265,268,271],{"class":195,"line":196},[193,229,230],{"class":199},"15",[193,232,234],{"class":233},"sbssI"," 22",[193,236,238],{"class":237},"sTEyZ"," *",[193,240,238],{"class":237},[193,242,238],{"class":237},[193,244,245],{"class":203}," cd",[193,247,248],{"class":203}," \u002Fhome\u002Fshop\u002Fotcms",[193,250,252],{"class":251},"sMK4o"," &&",[193,254,255],{"class":199}," docker",[193,257,204],{"class":203},[193,259,207],{"class":203},[193,261,210],{"class":203},[193,263,264],{"class":203}," otcms-backup",[193,266,267],{"class":251}," >>",[193,269,270],{"class":203}," backups\u002Fbackup.log",[193,272,273],{"class":251}," 2>&1\n",[275,276,277],"warning",{},[170,278,279,280,283,284,287],{},"A backup on the PC's own disk protects against a mistake, not against a stolen or dead PC. ",[179,281,282],{},"Take the USB drive home"," once a week, or set the copy location to a folder that leaves the premises. ",[174,285,286],{},"backups\u002Fbackup.log"," says when the last one ran; glance at it on the first of the month.",[165,289,291],{"id":290},"restoring","Restoring",[170,293,294],{},"On a fresh install with an empty database, from the system's folder:",[184,296,298],{"className":186,"code":297,"language":188,"meta":189,"style":189},"docker compose up -d otcms-postgres\ndocker compose run --rm --entrypoint sh otcms-backup -c 'pg_restore --clean --if-exists --dbname=\"$PGDATABASE\" \u002Fbackups\u002Fotcms-\u003Cdate>.dump'\ndocker compose up -d\n",[174,299,300,315,346],{"__ignoreMap":189},[193,301,302,304,306,309,312],{"class":195,"line":196},[193,303,200],{"class":199},[193,305,204],{"class":203},[193,307,308],{"class":203}," up",[193,310,311],{"class":203}," -d",[193,313,314],{"class":203}," otcms-postgres\n",[193,316,318,320,322,324,326,329,332,334,337,340,343],{"class":195,"line":317},2,[193,319,200],{"class":199},[193,321,204],{"class":203},[193,323,207],{"class":203},[193,325,210],{"class":203},[193,327,328],{"class":203}," --entrypoint",[193,330,331],{"class":203}," sh",[193,333,264],{"class":203},[193,335,336],{"class":203}," -c",[193,338,339],{"class":251}," '",[193,341,342],{"class":203},"pg_restore --clean --if-exists --dbname=\"$PGDATABASE\" \u002Fbackups\u002Fotcms-\u003Cdate>.dump",[193,344,345],{"class":251},"'\n",[193,347,349,351,353,355],{"class":195,"line":348},3,[193,350,200],{"class":199},[193,352,204],{"class":203},[193,354,308],{"class":203},[193,356,357],{"class":203}," -d\n",[170,359,360],{},"Everything comes back as it was at the time of the dump: users, catalogue, batches, sales, the audit trail. Sales made after the dump are gone, which is why the dump runs nightly and why a sale outside the system was never a good idea.",[165,362,364],{"id":363},"updates","Updates",[170,366,367,368,371],{},"The version the shop runs is pinned in ",[174,369,370],{},".env"," by its digest, so nothing changes until someone changes it. An update is:",[373,374,376,381,384,388,402,406,433],"steps",{"level":375},"3",[377,378,380],"h3",{"id":379},"back-up-first","Back up first",[170,382,383],{},"A migration that has applied to the database cannot be rolled back by starting the old version under it. Run the backup before every update.",[377,385,387],{"id":386},"change-the-version","Change the version",[170,389,390,391,394,395,397,398,401],{},"Set ",[174,392,393],{},"API_IMAGE"," in ",[174,396,370],{}," to the new digest and replace the web bundle in ",[174,399,400],{},"www\u002F"," with the one that matches it. Affram sends both with the release note.",[377,403,405],{"id":404},"pull-and-restart","Pull and restart",[184,407,409],{"className":186,"code":408,"language":188,"meta":189,"style":189},"docker compose pull otcms-api\ndocker compose up -d\n",[174,410,411,423],{"__ignoreMap":189},[193,412,413,415,417,420],{"class":195,"line":196},[193,414,200],{"class":199},[193,416,204],{"class":203},[193,418,419],{"class":203}," pull",[193,421,422],{"class":203}," otcms-api\n",[193,424,425,427,429,431],{"class":195,"line":317},[193,426,200],{"class":199},[193,428,204],{"class":203},[193,430,308],{"class":203},[193,432,357],{"class":203},[170,434,435],{},"The database migrates itself forward on start. The till is back in about a minute.",[165,437,439],{"id":438},"what-is-in-a-release","What is in a release",[170,441,442],{},"Every release is built and scanned in our pipeline and has run on our test box before it is offered to a shop. The release note says what changed in the words of the shop, and whether the update needs anything from the owner (a new setting, say) before it is applied.",[444,445,446],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}",{"title":189,"searchDepth":196,"depth":317,"links":448},[449,450,451,452],{"id":167,"depth":317,"text":168},{"id":290,"depth":317,"text":291},{"id":363,"depth":317,"text":364},{"id":438,"depth":317,"text":439},"A backup every night with a copy off the PC, a restore that is one command, and updates that are deliberate.","md",null,{},{"icon":144},{"title":141,"description":453},"2sErs8aoX2ojgMHN4WBTP8AGQcPnbW1Yp6KWb5vEhMs",[461,463],{"title":136,"path":137,"stem":138,"description":462,"icon":139,"children":-1},"The settings on the shop PC that let the day's figures reach the owner by e-mail and by SMS through Hubtel.",{"title":152,"path":153,"stem":154,"description":464,"icon":87,"children":-1},"Class C medicines and general goods. Where the rule comes from, what the system does about it, and what is still being confirmed.",1789486450931]