Skip to content

Commit

Permalink
feat: crate offer file
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelTaylor3D committed Aug 29, 2022
1 parent a0a7b59 commit 91f952e
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 1 deletion.
19 changes: 19 additions & 0 deletions src/controllers/staging.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ export const findAll = async (req, res) => {
}
};

export const generateOfferFile = async (req, res) => {
try {
await assertIfReadOnlyMode();
await assertStagingTableNotEmpty();
await assertHomeOrgExists();
await assertWalletIsSynced();
await assertNoPendingCommits();

const offerFile = await Staging.generateOfferFile();
res.json(offerFile);
} catch (error) {
console.trace(error);
res.status(400).json({
message: 'Error generating offer file.',
error: error.message,
});
}
};

export const commit = async (req, res) => {
try {
await assertIfReadOnlyMode();
Expand Down
24 changes: 24 additions & 0 deletions src/datalayer/persistance.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,4 +437,28 @@ const getMirrors = async (storeId) => {
}
};

export const makeOffer = async (offer) => {
const options = {
url: `${rpcUrl}/make_offer `,
body: JSON.stringify(offer),
};

try {
const response = await request(
Object.assign({}, getBaseOptions(), options),
);

const data = JSON.parse(response);

if (data.success) {
return data;
}

throw new Error(data.error);
} catch (error) {
console.log(error);
throw error;
}
};

export const addMirror = _addMirror;
178 changes: 177 additions & 1 deletion src/models/staging/staging.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@

import _ from 'lodash';
import Sequelize from 'sequelize';
const Op = Sequelize.Op;

const { Model } = Sequelize;
import { Project, Unit, Organization, Issuance } from '../../models';
import { encodeHex } from '../../utils/datalayer-utils';
import { encodeHex, generateOffer } from '../../utils/datalayer-utils';

import * as rxjs from 'rxjs';
import { sequelize } from '../../database';

import datalayer from '../../datalayer';
import { makeOffer } from '../../datalayer/persistance';

import ModelTypes from './staging.modeltypes.cjs';
import { formatModelAssociationName } from '../../utils/model-utils.js';

import {
createXlsFromSequelizeResults,
transformFullXslsToChangeList,
} from '../../utils/xls';

class Staging extends Model {
static changes = new rxjs.Subject();

Expand All @@ -32,6 +40,174 @@ class Staging extends Model {
return super.upsert(values, options);
}

static generateOfferFile = async () => {
const stagingRecord = await Staging.findOne({
// where: { isTransfer: true },
where: { commited: false },
raw: true,
});

const takerProjectRecord = _.head(JSON.parse(stagingRecord.data));

const myOrganization = await Organization.findOne({
where: { isHome: true },
raw: true,
});

const maker = { inclusions: [] };
const taker = { inclusions: [] };

// The record still has the orgUid of the takerProjectRecord,
// we will update this to the correct orgUId later
maker.storeId = takerProjectRecord.orgUid;
taker.storeId = myOrganization.orgUid;

const makerProjectRecord = await Project.findOne({
where: { warehouseProjectId: takerProjectRecord.warehouseProjectId },
include: Project.getAssociatedModels().map((association) => {
return {
model: association.model,
as: formatModelAssociationName(association),
};
}),
});

makerProjectRecord.projectStatus = 'Transitioned';

const issuanceIds = makerProjectRecord.issuances.reduce((ids, issuance) => {
if (!ids.includes(issuance.id)) {
ids.push(issuance.id);
}
return ids;
}, []);

let unitMakerRecords = await Unit.findAll({
where: {
issuanceId: { [Op.in]: issuanceIds },
},
raw: true,
});

// Takers get an unlatered copy of all the project units from the maker
const unitTakerRecords = _.cloneDeep(unitMakerRecords);

unitMakerRecords = unitMakerRecords.map((record) => {
record.unitStatus = 'Exported';
return record;
});

const primaryProjectKeyMap = {
project: 'warehouseProjectId',
projectLocations: 'id',
labels: 'id',
issuances: 'id',
coBenefits: 'id',
relatedProjects: 'id',
estimations: 'id',
projectRatings: 'id',
};

const primaryUnitKeyMap = {
unit: 'warehouseUnitId',
labels: 'id',
label_units: 'id',
issuances: 'id',
};

const makerProjectXslsSheets = createXlsFromSequelizeResults({
rows: [makerProjectRecord],
model: Project,
toStructuredCsv: true,
});

const takerProjectXslsSheets = createXlsFromSequelizeResults({
rows: [takerProjectRecord],
model: Project,
toStructuredCsv: true,
});

const makerUnitXslsSheets = createXlsFromSequelizeResults({
rows: unitMakerRecords,
model: Unit,
toStructuredCsv: true,
});

const takerUnitXslsSheets = createXlsFromSequelizeResults({
rows: unitTakerRecords,
model: Unit,
toStructuredCsv: true,
});

const takerProjectInclusions = await transformFullXslsToChangeList(
takerProjectXslsSheets,
'insert',
primaryProjectKeyMap,
);

const makerProjectInclusions = await transformFullXslsToChangeList(
makerProjectXslsSheets,
'insert',
primaryProjectKeyMap,
);

const makerUnitInclusions = await transformFullXslsToChangeList(
makerUnitXslsSheets,
'insert',
primaryUnitKeyMap,
);

const takerUnitInclusions = await transformFullXslsToChangeList(
takerUnitXslsSheets,
'insert',
primaryUnitKeyMap,
);

/* Object.keys(maker.inclusions).forEach((table) => {
maker.inclusions[table] = maker.inclusions[table]
.filter((inclusion) => inclusion.action !== 'delete')
.map((inclusion) => ({ key: inclusion.key, value: inclusion.value }));
});*/

maker.inclusions.push(
...makerProjectInclusions.project
.filter((inclusion) => inclusion.action !== 'delete')
.map((inclusion) => ({
key: inclusion.key,
value: inclusion.value,
})),
);

maker.inclusions.push(
...makerUnitInclusions.unit
.filter((inclusion) => inclusion.action !== 'delete')
.map((inclusion) => ({
key: inclusion.key,
value: inclusion.value,
})),
);

taker.inclusions.push(
...takerProjectInclusions.project
.filter((inclusion) => inclusion.action !== 'delete')
.map((inclusion) => ({
key: inclusion.key,
value: inclusion.value,
})),
);

taker.inclusions.push(
...takerUnitInclusions.unit
.filter((inclusion) => inclusion.action !== 'delete')
.map((inclusion) => ({
key: inclusion.key,
value: inclusion.value,
})),
);

const offer = generateOffer(maker, taker);
return makeOffer(offer);
};

// If the record was commited but the diff.original is null
// that means that the original record no longer exists and
// the staging record should be cleaned up.
Expand Down
4 changes: 4 additions & 0 deletions src/routes/v1/resources/staging.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ StagingRouter.get('/', validator.query(stagingGetQuerySchema), (req, res) => {
return StagingController.findAll(req, res);
});

StagingRouter.get('/offer', (req, res) => {
return StagingController.generateOfferFile(req, res);
});

StagingRouter.put('/', (req, res) => {
return StagingController.editRecord(req, res);
});
Expand Down
18 changes: 18 additions & 0 deletions src/utils/datalayer-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,21 @@ export const keyValueToChangeList = (key, value, includeDelete) => {

return changeList;
};

export const generateOffer = (maker, taker) => {
return {
maker: [
{
store_id: maker.storeId,
inclusions: maker.inclusions,
},
],
taker: [
{
store_id: taker.storeId,
inclusions: taker.inclusions,
},
],
fee: 0,
};
};

0 comments on commit 91f952e

Please sign in to comment.