Skip to content

Commit 6a3297a

Browse files
authored
Merge pull request #4302 from LiteFarmOrg/integration
Release 3.13.0
2 parents ec53181 + 978a798 commit 6a3297a

196 files changed

Lines changed: 7961 additions & 4680 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* Copyright 2026 LiteFarm.org
3+
* This file is part of LiteFarm.
4+
*
5+
* LiteFarm is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* LiteFarm is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
14+
*/
15+
16+
/**
17+
* Reorganizes the certification tables to support multiple certifications per farm:
18+
* - Renames `certifications` → `certification_system_type` with column renames
19+
* - Renames `organicCertifierSurvey` → `certification` with column renames and new fields
20+
* - Soft-deletes `interested = false` rows (no previously deleted rows exist, so `down` can safely reverse this)
21+
*
22+
* @param { import("knex").Knex } knex
23+
* @returns { Promise<void> }
24+
*/
25+
export const up = async function (knex) {
26+
// Step 1: Soft-delete interested=false rows before schema changes.
27+
await knex('organicCertifierSurvey').where({ interested: false }).update({ deleted: true });
28+
29+
// Step 2: Rename certifications → certification_system_type and rename all columns
30+
await knex.schema.renameTable('certifications', 'certification_system_type');
31+
await knex.schema.alterTable('certification_system_type', (table) => {
32+
table.renameColumn('certification_id', 'id');
33+
table.renameColumn('certification_type', 'name');
34+
table.renameColumn('certification_translation_key', 'translation_key');
35+
});
36+
37+
// Recreate certifiers FK referencing the new table and column names
38+
await knex.schema.alterTable('certifiers', (table) => {
39+
table.dropForeign('certification_id');
40+
table.renameColumn('certification_id', 'system_type_id');
41+
table.foreign('system_type_id').references('id').inTable('certification_system_type');
42+
});
43+
44+
// Step 3: Rename organicCertifierSurvey → certification with column renames and new columns
45+
// Drop constraints
46+
await knex.raw(
47+
`ALTER TABLE "organicCertifierSurvey" DROP CONSTRAINT IF EXISTS "organiccertifiersurvey_certification_id_foreign"`,
48+
);
49+
await knex.raw(
50+
`ALTER TABLE "organicCertifierSurvey" DROP CONSTRAINT IF EXISTS "organiccertifiersurvey_farm_id_unique"`,
51+
);
52+
53+
await knex.schema.renameTable('organicCertifierSurvey', 'certification');
54+
await knex.schema.alterTable('certification', (table) => {
55+
table.renameColumn('survey_id', 'id');
56+
table.renameColumn('certification_id', 'system_type_id');
57+
table.renameColumn('requested_certification', 'requested_system_type');
58+
59+
table.boolean('is_active').notNullable().defaultTo(false);
60+
table
61+
.enu('certification_type', [
62+
'ORGANIC',
63+
'BIODYNAMIC',
64+
'REGENERATIVE',
65+
'CERTIFIED_HUMANE',
66+
'FAIR_TRADE',
67+
'GRASSFED/PASTURE',
68+
'SUSTAINABILITY',
69+
'ANIMAL_WELFARE',
70+
'NON-GMO',
71+
'CARBON/CLIMATE',
72+
])
73+
.nullable();
74+
table.string('certificate_number').nullable();
75+
table.string('certificate_member_id').nullable();
76+
table.date('issue_date').nullable();
77+
table.date('valid_until').nullable();
78+
table.text('certificate_document_url').nullable();
79+
80+
table.dropColumn('interested');
81+
});
82+
83+
// Add FK for system_type_id after columns are in place
84+
await knex.schema.alterTable('certification', (table) => {
85+
table.foreign('system_type_id').references('id').inTable('certification_system_type');
86+
});
87+
88+
// Step 4: Rename permissions
89+
await knex('permissions')
90+
.where({ name: 'get:organic_certifier_survey' })
91+
.update({ name: 'get:certification', description: 'get certification' });
92+
await knex('permissions')
93+
.where({ name: 'add:organic_certifier_survey' })
94+
.update({ name: 'add:certification', description: 'add certification' });
95+
await knex('permissions')
96+
.where({ name: 'edit:organic_certifier_survey' })
97+
.update({ name: 'edit:certification', description: 'edit certification' });
98+
await knex('permissions')
99+
.where({ name: 'delete:organic_certifier_survey' })
100+
.update({ name: 'delete:certification', description: 'delete certification' });
101+
};
102+
103+
/**
104+
* @param { import("knex").Knex } knex
105+
* @returns { Promise<void> }
106+
*/
107+
export const down = async function (knex) {
108+
// Restore permissions
109+
await knex('permissions')
110+
.where({ name: 'get:certification' })
111+
.update({ name: 'get:organic_certifier_survey', description: 'get organic_certifier_survey' });
112+
await knex('permissions')
113+
.where({ name: 'add:certification' })
114+
.update({ name: 'add:organic_certifier_survey', description: 'add organic_certifier_survey' });
115+
await knex('permissions').where({ name: 'edit:certification' }).update({
116+
name: 'edit:organic_certifier_survey',
117+
description: 'edit organic_certifier_survey',
118+
});
119+
await knex('permissions').where({ name: 'delete:certification' }).update({
120+
name: 'delete:organic_certifier_survey',
121+
description: 'delete organic_certifier_survey',
122+
});
123+
124+
// Drop system_type_id FK before renaming columns and table
125+
await knex.schema.alterTable('certification', (table) => {
126+
table.dropForeign('system_type_id');
127+
});
128+
129+
await knex.schema.renameTable('certification', 'organicCertifierSurvey');
130+
131+
await knex.schema.alterTable('organicCertifierSurvey', (table) => {
132+
table.dropColumn('certificate_document_url');
133+
table.dropColumn('valid_until');
134+
table.dropColumn('issue_date');
135+
table.dropColumn('certificate_member_id');
136+
table.dropColumn('certificate_number');
137+
table.dropColumn('certification_type');
138+
table.dropColumn('is_active');
139+
140+
table.boolean('interested').notNullable().defaultTo(false);
141+
table.unique('farm_id');
142+
143+
table.renameColumn('requested_system_type', 'requested_certification');
144+
table.renameColumn('system_type_id', 'certification_id');
145+
table.renameColumn('id', 'survey_id');
146+
});
147+
148+
// Drop certifiers FK and rename column before renaming certification_system_type back
149+
await knex.schema.alterTable('certifiers', (table) => {
150+
table.dropForeign('system_type_id');
151+
table.renameColumn('system_type_id', 'certification_id');
152+
});
153+
154+
await knex.schema.alterTable('certification_system_type', (table) => {
155+
table.renameColumn('translation_key', 'certification_translation_key');
156+
table.renameColumn('name', 'certification_type');
157+
table.renameColumn('id', 'certification_id');
158+
});
159+
await knex.schema.renameTable('certification_system_type', 'certifications');
160+
161+
// Recreate FKs referencing the restored certifications table
162+
await knex.schema.alterTable('certifiers', (table) => {
163+
table.foreign('certification_id').references('certification_id').inTable('certifications');
164+
});
165+
// Recreate organicCertifierSurvey FK (dropped in up() before the table was renamed)
166+
await knex.schema.alterTable('organicCertifierSurvey', (table) => {
167+
table.foreign('certification_id').references('certification_id').inTable('certifications');
168+
});
169+
170+
// Restore soft-deleted rows: all deleted=true rows were soft-deleted in up() (no prior deletes existed).
171+
// The interested column was re-added with defaultTo(false), so non-deleted rows need interested=true restored.
172+
await knex('organicCertifierSurvey').where({ deleted: false }).update({ interested: true });
173+
await knex('organicCertifierSurvey').where({ deleted: true }).update({ deleted: false });
174+
};
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2026 LiteFarm.org
3+
* This file is part of LiteFarm.
4+
*
5+
* LiteFarm is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* LiteFarm is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
14+
*/
15+
16+
/**
17+
* @param { import("knex").Knex } knex
18+
* @returns { Promise<void> }
19+
*/
20+
export const up = async function (knex) {
21+
await knex.schema.table('certification', (table) => {
22+
table.renameColumn('requested_certifier', 'other_certifier');
23+
});
24+
};
25+
26+
export const down = async function (knex) {
27+
await knex.schema.table('certification', (table) => {
28+
table.renameColumn('other_certifier', 'requested_certifier');
29+
});
30+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2026 LiteFarm.org
3+
* This file is part of LiteFarm.
4+
*
5+
* LiteFarm is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* LiteFarm is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
14+
*/
15+
16+
/**
17+
* Certificate document upload is being removed from certifications entirely.
18+
*
19+
* @param { import("knex").Knex } knex
20+
* @returns { Promise<void> }
21+
*/
22+
export const up = async function (knex) {
23+
await knex.schema.alterTable('certification', (table) => {
24+
table.dropColumn('certificate_document_url');
25+
});
26+
};
27+
28+
/**
29+
* @param { import("knex").Knex } knex
30+
* @returns { Promise<void> }
31+
*/
32+
export const down = async function (knex) {
33+
await knex.schema.alterTable('certification', (table) => {
34+
table.text('certificate_document_url').nullable();
35+
});
36+
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2026 LiteFarm.org
3+
* This file is part of LiteFarm.
4+
*
5+
* LiteFarm is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* LiteFarm is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
14+
*/
15+
16+
/**
17+
* @param { import("knex").Knex } knex
18+
* @returns { Promise<void> }
19+
*/
20+
export const up = async function (knex) {
21+
await knex('permissions').insert([
22+
{
23+
permission_id: 192,
24+
name: 'get:certification_meta',
25+
description:
26+
'get whether the farm holds any certification, without the certification records themselves',
27+
},
28+
]);
29+
await knex('rolePermissions').insert([
30+
{ role_id: 1, permission_id: 192 },
31+
{ role_id: 2, permission_id: 192 },
32+
{ role_id: 3, permission_id: 192 },
33+
{ role_id: 5, permission_id: 192 },
34+
]);
35+
};
36+
37+
/**
38+
* @param { import("knex").Knex } knex
39+
* @returns { Promise<void> }
40+
*/
41+
export const down = function (knex) {
42+
return Promise.all([
43+
knex('rolePermissions').where({ permission_id: 192 }).del(),
44+
knex('permissions').where({ permission_id: 192 }).del(),
45+
]);
46+
};

0 commit comments

Comments
 (0)