Skip to content

OpenConstructionERP v18.0.0

Choose a tag to compare

@github-actions github-actions released this 24 Sep 15:29
· 2954 commits to main since this release

The AI assistant can now do the work, not only talk about it, and nothing it prepares reaches the project until a person applies it. Ask it to add or change a BOQ position, create a task, raise an RFI, log a risk, add a punch item or update the progress of a schedule activity, and it answers with a card that shows exactly what would be written, with the current and proposed values side by side, notes on anything it could not settle (an assignee name that matches two people, a line linked to a master) and a plain reason when the change cannot be made. The card is applied, edited first, rejected, or later undone, each by a person with the right role in that project, and every step lands in the project history under that person's name. Undo refuses to overwrite a record somebody edited after the change was applied, and says so. The assistant itself now sits beside the page instead of over it, so the estimate or schedule it talks about stays in view; the panel is resized by dragging, opens and closes with a keyboard shortcut, and has a Changes tab that lists everything the assistant proposed across a project or all projects, filtered by status, with who decided what. A new user guide page walks through the whole flow.

Several things that the full test suite had been flagging on every nightly run since 20 September are fixed. A change published after a database commit could fire while an inner savepoint was released and the outer transaction was still open, so the map pin placed for a new project's address was written before the project existed and failed; publishing now waits for the real commit. The bulk placement of project map pins spent its batch of 200 on projects that already had a pin, so on a larger installation a new project never got one; it now takes only the projects still missing a pin, newest first.

Contracts: a draft contract whose claims have already left draft can no longer be deleted, because deleting it took those claims with it; the refusal now reaches the user in their own language and says to terminate the contract instead. Closing a contract or creating a final account no longer produces a final account that is already closed. The hint on a locked claim no longer promises that rejecting it puts it back in draft; it says to reject it and raise a new draft claim. The AIA G702 and G703 PDF, the methodology exports and the daily diary PDF are drawn in a worker thread, so a large one no longer stalls every other request.

Operations: workers sharing one PostgreSQL no longer report a clean schema repair they did not run. A worker that finds the repair in progress waits for it and checks the schema itself, so schema_heal_incomplete is true on every worker whose role could not apply it, and the upgrade check refuses a start where it is not false. Backups and project bundles are built on disk instead of in memory, so a large export no longer holds the whole archive in RAM, which matters on the 3 GB floor.

Smaller fixes: project lists page in a stable order, so past 500 projects no row is skipped or shown twice. The estimates list keeps working when a project is archived or unshared while it is open, and names the projects it leaves out. The ready-made pack card in onboarding is offered only to an administrator, who is the only one allowed to install it; the first-run tour is started by the server's onboarding state and no longer pops up over the setup wizard, which now has its own tab title. The RFQ screen counts and filters by the statuses the server actually uses, so its open count is no longer always zero. The Edit dialog of a purchase order past draft keeps the vendor, currency, lines and tax as they were approved and says how to correct them. Closed quality and safety records (inspections, NCRs, meetings, submittals, HSE and carbon records) are kept instead of deleted and can be voided or cancelled; a billed pay application cannot be rejected, an award cannot be deleted while its purchase order exists, evaluation bounds and stock item units and costs are frozen once verdicts or movements rely on them, and a retention release without a lien waiver is warned about. More bookkeeping records across construction control, contacts, CRM, field reports, meetings, property development, QMS, resources and delay analysis keep their figures once work relies on them.

A project's map shows the site again: its streets and the buildings along them. The map inside a project only ever had the 3D globe, and since 16.2.0 the only background that globe has had is shaded relief, because the raster street tiles it used to draw started demanding a key and printing a watermark, so they were taken out. Zoomed onto a site it showed landform and nothing a person standing there would recognise, while the global map page next door already drew full street maps. The project map now opens on that same 2D street map, drawn from OpenStreetMap data through OpenFreeMap, centred on the project's location and tilted so the buildings stand up as blocks, with the safety, punch list and site photo pins and any drawing placed on the map. The basemap choice is shared with the global map, every tile still comes through the application's own server, and the ODbL attribution is shown. A project with no location yet is placed by clicking the map. The 3D globe is one click away in the header and is still where 3D models live: a link to a model or a plot opens the globe directly, and so does moving or cropping a drawing's corners, because that editor is built on the globe. The choice between the two is remembered per browser.

Onboarding asks what the company does instead of how big the team is. Team size says how many people will use the tool and nothing about which tools they need, so a small civil firm and a small fit-out shop were given the same modules. The profile step now leads with the business profiles, shows the full platform as its own card beneath them, and folds the job profiles, planner, site supervisor, HSE lead and the rest, into a group for a person setting the tool up for their own job. Picking a card names the modules it switches on before the user moves on, and the module step starts from that set. Walking the whole flow turned up faults that are fixed here. A user who picked modules one by one, or took the full platform and switched some of it off, was saved as the full platform, so the modules they had just turned off were back on the next screen; the full platform is now saved only while every module is on, and otherwise exactly the modules on screen are saved. The profile card, the module step and the summary counted a core module twice when a profile listed it again, so one pick showed three different totals. With a job profile picked, the button that folds the role group did nothing. And the summary on the last screen names the profile that is actually saved, so a quick start that saves the full platform says so. The server now refuses a profile it does not know, a typo or one that no longer exists, instead of storing it as the user's profile and reading it back later as if it were one, and switching profile from the Modules page no longer clears the team size given earlier. Every profile now also switches on the modules its own modules depend on, which 23 of the 26 profiles did not, so takeoff no longer arrives without CAD or reporting without the BIM hub. Five profiles had a gap a person in that role would hit on the first day, and they are closed: a subcontractor gets contracts, which its pay applications live in, an owner gets contracts and change orders, an MEP contractor gets safety, a civil firm gets RFIs, submittals and meetings, and an estimator gets the BIM hub and CAD. On screen every switch on the module step is now named after its module, where a screen reader used to announce about 150 unnamed switches. The new text is translated into every language.

A contract signed from this release on holds retention at its country's ladder. The regional packs have long declared how retention steps down as a job progresses, and the payment engine only ever applied a ladder from a record that nothing wrote, so a United States contract kept its opening rate to the last claim while the pack beside it said the rate halves at half complete. On a 100,000 contract billed to sixty per cent that is 6,000 held where the ladder says 5,500. The ladder is written when the contract is signed, so a later correction to a pack or a change to the project's country cannot rewrite what a signed contract withholds, and it is written only where the pack's opening rate is the rate the parties agreed. Where it is not written, the contract records why. A project with no country, or in a country whose pack is silent on retention, keeps the flat rate it had, and that is every installation that has not set a country up. Cost-plus and time and materials contracts are left out, and a policy somebody already wrote is never overwritten. Two checks come with it. A claim whose retention passes a cap stated in the contract's policy is blocked, and where no cap is stated but the country limits retention by state law, the check says no state could be resolved for the project and asks for the state's limit to be written into the policy as a cap, which for now is done through the API. A contract that carries more than one retention schedule gets a warning, because two schedules are ambiguous about the money. The retention schedules a ladder is read from are also held to the lock 17.8.3 put on the policy: once a claim on the contract has gone out, a ladder can no longer be added, rewritten or removed through them, and the refusal names the claim that locked it.

A payment certificate now adds up when claims bill money that no schedule of values line carries. This is the case 17.8.3 named as still open, a cost-plus contract billed from its costs one month and against its schedule the next, and it reaches further than cost-plus, because a claim can also bill past its lines. Column D is assembled from claim lines, so that money never reached it, while line 7 still counted the certificate it was billed on, and line 8 subtracted money the columns had never added. Line 8 is floored at zero, so however large the gap was the certificate said nothing was due; in the case we measured, the contractor was shown nothing due against 27,000 owed. The continuation sheet now carries a row of its own for that money. Once a later month was billed against the schedule, line 7 could miss that money as well, because it was read from the previous claim's frozen figure, which is assembled from schedule lines; that went unnoticed because line 4 missed it by the same amount and the two cancelled. Line 7 is now worked out from each earlier claim's own billed figures whenever an earlier month billed money with no line behind it. The new row reaches claims certified from now on, and no certificate that has already gone to a payer is rewritten.

On that row the scheduled value, the percent complete and the balance to finish are left blank, because there is nothing to measure the money against, and column G carries the work. The totals row adds up only the cells that have an answer, so the balance to finish in the total is what is left on the schedule lines. On screen the row's description follows the reader's language where there is a translation for it, which today is German and Russian, and reads in English in every other language; the printed form is written in English and says so, and there the row is in English with the rest of the page. Retention on that money is counted once on line 5 of the G702. It is held at the contract's flat rate even under a ladder, because a ladder follows progress on the schedule and this money is not part of it, and column I on the row shows the retention those claims actually stored. The retention engine measures the schedule alone, the certificate adds the row back into lines 4 and 5, and the amount due on the certificate and the net due stored on the claim come from the same calculation. A release is shared between the schedule and the row in proportion to what each has held and is worked out again at every claim, so releasing everything clears both: on 200,000 retained at 10 per cent until half complete and nothing after, a final release of 12,000 clears line 5 to zero and pays the 12,000.

A claim also records what its gross is made of. On a cost-plus or time and materials claim, typing a single breakdown row by hand against a 50,000 claim made the claim worth that row, because the gross was read back off the lines whenever there were any. The gross now stays what the recorded cost made it, and a breakdown that asks for more than the claim does is refused at submission. Populating such a claim from site progress turns it into a claim that follows its lines from then on, and a claim written before this release keeps the behaviour it had.

The schedule of values tracker shows the retention each certificate recorded for a line, instead of working it out again as the flat rate times what was billed. On a laddered contract the two disagree: at sixty per cent of a 100,000 contract the certificate said 5,500 held and the tracker said 6,000, and a person with both screens open could not tell which was the job's retention. On a contract with a flat rate a single line can differ by one cent either way from what the tracker showed before, because the certificate spread the cents across the lines when it was produced; the lines still add up to the same total. Cost-plus and time and materials claims record no figure per line and keep the computed one.

The schedule of values lines a job is billed on stay put. The server now refuses to edit or delete a line once the contract is signed, which the contract screen already did, and the refusal says a change order is the way to change it. A draft contract can carry claims too, certified and paid ones included, so a line any claim has billed on is locked on a draft as well. Deleting such a line used to take every claim line billed against it, leaving the claim with a gross, a retention and a net due and nothing to explain them. The contract screen now shows no Edit or Delete on that line, and a note under the table gives the claim as the reason, in the reader's language. A draft contract that a claim has billed on can no longer be deleted, and the refusal says to take the lines off a claim that is still a draft or to terminate the contract. A progress claim that has left draft can no longer be deleted either. No screen offered that, but the route answered, and every later certificate would then have been worked out as if the claim had never been issued. Adding a new line to a signed contract is still allowed, and whether a change order should be what adds it is left open. When the server refuses to change a claim that has left draft, its message now names only what can be done: reject it and raise a new draft claim, raise a new draft claim if it was already rejected, or correct a certified or paid one on the next claim. It used to tell even a rejected claim to reject itself to reopen, and nothing returns a rejected claim to draft.

Closing a contract no longer rewrites a final account somebody signed off. The Close button sent the contract value as the final contract value, so an account agreed at a negotiated figure was overwritten with the contract sum the moment the contract was closed, and a Close without a sign-off date wiped the recorded one. Close now sends a status and no figures. An agreed or closed account keeps its figures, its sign-off and its notes, and a contract with no final account yet gets one worked out from the contract and its claims, the same number as before. Editing or deleting the final account directly follows the same rule: its status moves only along its lifecycle, an agreed or closed account cannot be deleted, and reopening an agreed figure means disputing the account first and then agreeing the new one. The final account kept under variations holds the value it closed at, where an edit could rewrite it or set it back to draft and a variation completed after the close still moved it. Each completed variation now moves the contract sum exactly once, through the handler that checks the project, the currency and duplicates, and leaves a terminated or completed contract at its agreed value. A second handler that failed with an error in the log on every completed variation, without ever moving a value, is gone.

On a German job, a subcontractor's construction tax exemption certificate is read on the day each pay application is paid, which is when the German pack says it counts, instead of at the claim's period end. A certificate valid on 31 March and expired by the day the money went out in May read as met, and the payment, which the law then taxes at 15 per cent of the gross with VAT included, went through without a word. A new check now warns about it and names the withholding the law requires, with its rate, whether VAT is in the base and the annual small-amount limit from the German scheme, and says that the deduction is not made here. It never blocks and deducts nothing. The payment day is the day the pay application was marked paid in the platform, since a bank value date is not recorded. Before payment the claim says the certificate will be read on the payment date and when the one on file ends, and the claim panel lists in red a certificate that nothing on file could cover. An exemption that has run out no longer blocks submitting the claim, because the law decides the tax on the payment, not whether the work may be billed. The packs of other countries behave exactly as before.

Records that were signed off, sent, approved, paid or decided now keep their figures, and a refusal says what to do instead. Across the product such a record was protected on its own edit screen and could still be rewritten another way, by a delete that took its children with it, by a plain update, or by a route no screen calls. Those ways are closed, each with a refusal that names the remedy, and a form that sends the stored values back unchanged is not refused. An approved, locked bill of quantities no longer changes behind its approval. Restoring an older snapshot over it, duplicating a line inside it, deleting it, moving its status through a plain update and applying an estimate from the estimate builder into it are all refused, and the refusal points at a revision or a new bill. Archiving an approved bill now means unlocking it first. Editing a code shared across the project still updates the open bills and leaves the locked ones alone, and the editor names the estimates it skipped and says to unlock them or create a revision to take the change.

Tenders stay decided. Once a package is awarded or closed, a bid's total, currency and priced lines can no longer be changed and no new bid can be added, so a losing bid cannot be repriced after the decision, and the tender page stops offering Add Bid. A package is awarded only by applying the winning bid, which names the winner and carries its rates into the bill, where a plain status change could leave it awarded with no winner at all. In bid management a bid is recorded only while the package is out to tender, the bids, lines, bidders and invitations of an awarded or cancelled package can no longer be deleted, and deleting one that does not exist says so instead of answering as if it had worked. An RFQ moves only along its own lifecycle, keeps its scope and evaluation basis once vendors have been asked to price, and can be deleted only as a draft. A purchase order keeps the figures it was approved with, which is the sum finance committed to at that moment. Editing the amounts, vendor or lines of an issued order is now refused with the remedy, which is to cancel the order and reopen it; an approved order goes back to draft with the correction and is approved again, and a received one takes a separate order for the difference. Notes, dates and payment terms stay editable throughout.

Money that has been paid or certified stays on record. An invoice that is approved, sent, paid or cancelled keeps its amounts, tax, counterparty and lines, and the refusal says to cancel it and reopen it as a draft, or to issue a credit note once it is paid, while notes, due dates and a legal status move still save. A subcontract agreement that holds any payment application or retention entry is no longer deleted along with them and is closed through its status instead, and a work package billed on a pay application stays. A completed or voided variation order and a decided variation request are kept rather than deleted, because deleting an order left the contract sum raised while the final account stopped counting it. In property development, a development, plot or buyer with sales contracts beyond draft, paid instalments, reservations with a deposit, handovers, warranty claims, escrow transactions or broker commissions under it can no longer be deleted: the refusal counts what would have gone and points at completing or pausing the development, or cancelling the buyer. A payment schedule with paid instalments is no longer rebuilt as unpaid, and an escrow transaction that has been matched to the bank statement or is under dispute is corrected by an entry in the opposite direction rather than deleted. An NCR raises one change order however often it is asked, and a void NCR raises none. In construction control a failed inspection can no longer be turned into a passed one by a plain edit, with no result, no performer and no NCR, an as-built record can no longer skip its tolerance check and the manager's sign-off on its way to verified, and reading an issued handover package no longer rewrites it. In health and safety a corrective action is completed, cancelled or escalated only through its own actions, with the permissions and the closure evidence those actions ask for.

The estimates list loads every project's bills in one request instead of one per project. A workspace with 44 projects made 44 requests, and a browser runs six requests to one server at a time, so most of the wait was queueing. The list also no longer hides a project it could not read. A project archived or unshared while the page was open dropped out of the list and out of every total above it, with nothing on screen to say so. The list now fails as a whole and names those projects with a Retry button, showing no estimates, count or totals meanwhile, and Retry reloads the project list first, so a project that is really gone drops out and the list comes back.

Opening the estimates list from the menu no longer downloads the bill editor. Hovering the menu item fetched 39 files and about 930 KB, two thirds of it the grid, 3D and PDF libraries the list does not use, all queued ahead of the list's own data; the editor still loads when an estimate is opened. The dashboard and the sidebar read the module catalogue once between them instead of twice, about 100 KB less on every dashboard open, and the sidebar now refreshes after a pack is installed instead of showing the old module set. Every project picker and filter stopped silently at the first 50 projects, because the list comes in pages and said nothing about the rest; they now read the whole list, in one request up to 500 projects. Searching the cost database from Add from Database fetches slim rows and reads the full item only for what is picked. The heaviest exports, backups, the COBie and bill of quantities workbooks built from a model, punch list PDFs, the closeout package, property sales documents and project bundles, now render beside the request loop, so one person's export no longer makes every other request on a small server wait, the health check included. Generating a claim on a 500 line schedule of values used to write each line's retention with its own statement, 517 statements in all, and now sends 21. New database indexes cover lists that were read without one, five of them on a database upgraded from 17.8.3, among them the quantity rules page, which listed a table with no index at all, and the contacts list, whose access rule forced a full scan of the table.

Exporting a bill of quantities to Excel gives the file the server writes, as CSV, GAEB and BC3 already did. The toolbar used to build the workbook in the browser, and that file carried no company letterhead, named no project, classification standard or region, and printed the gross total with no currency. The server file carries the letterhead, the header block the importers read back, a position id column that survives a round trip, the currency of every row and the frozen exchange rates, and money taken from the authoritative total, where the browser's own arithmetic kept a single tax markup and lost the rest on a bill that has two. The project, standard and region are printed on a line above the table on every export, with or without a company profile. Two things change that are not improvements. Exporting to Excel now needs the network, and the cost summary at the foot of the sheet reads direct cost, a row for each markup and a grand total instead of net, VAT and gross, because those are the figures the rest of the product treats as authoritative. The sheet's own text, its column headers and the project line, is English, and the file now says so rather than claiming the reader's language. The PDF export, which is still drawn in the browser, now carries the project name and currency, which it had been printing empty.

An approval step that names one approver and asks for two or more approvals is refused when the route is saved. It never waited for more than that one person, so the number promised a second pair of eyes nobody would be asked for; the refusal names the step and says to give it a role with that count or to drop the count. Routes saved before keep working, and their dry run warns that the count is never reached. The API no longer describes the server to anyone who can reach its port. The system status, the version check, the module list, the pack routes and the region statistics now need a signed-in caller, and only the workspace branding that the sign-in screen shows stays open, so a script that read them without a token now gets 401 and has to sign in first. The unit mismatch check no longer suggests changing a project unit system setting that does not exist; it leads with the conversion and says the measurement system follows from the project's country.

The macOS installer is for Apple Silicon only. Both macOS files on the release page are built for it and nothing is published for Intel Macs; the download badge and the install guide now say so and point an Intel Mac owner at pip or Docker. The application no longer takes over the log handlers of the process that hosts it. Starting it closed every handler already installed, so an embedding process or a test's log capture stopped receiving records without any error; the console output is unchanged. Installing from PyPI now caps every runtime dependency below its next major version, so a new major release upstream cannot break a fresh install, and nothing resolves differently today.

For operators upgrading from 17.8.3: the schema gains one column, oe_contracts_progress_claim.gross_basis, and five indexes. The code declares seven, and a database created by 17.8.3 already has two of them, ix_oe_hse_advanced_certification_owner_user_id and ix_oe_hse_advanced_ppe_issue_recipient_user_id. On PostgreSQL the application adds the column and the indexes on its first start. We upgraded a real 17.8.3 installation to check this: the first start added the one column and the five indexes and nothing else, and old claims, the G702 and G703 as JSON and as PDF, and new claims all worked afterwards.

If the application connects to PostgreSQL with a role that cannot change the schema, it still starts, but every read of a progress claim fails until the owner of the table runs this once:

ALTER TABLE oe_contracts_progress_claim ADD COLUMN IF NOT EXISTS gross_basis varchar(10);

No restart is needed after it. Such a start no longer looks clean. Until this release the repair caught each refused statement on its own, so health said healthy with schema_heal_failed: false and the only trace was a warning per statement. Now the boot log ends the repair with one ERROR line that lists every statement the database refused together with the SQL to run as the owner, GET /api/system/upgrade/status returns the same list to an administrator, and /api/health reports schema_heal_incomplete: true with the count in schema_heal_skipped_count. Health names no table, since it answers anyone. Its status stays healthy on purpose, because a restart cannot give the role the right it lacks and a watchdog that restarts on degraded would only loop. The field describes the last start, so it keeps reading true until the next one even after the SQL has been run.

Do not run alembic upgrade head on an existing installation to get there.

Full Changelog: v17.8.3...v18.0.0