Add product price history model and database schema: Implement associations for ProductPriceHistory with ProductType and RegionData. Update FalukantService to utilize active character for user-related operations. Ensure product price history table exists in the database with appropriate structure and indexing.

This commit is contained in:
Torsten Schulz (local)
2026-02-04 09:02:51 +01:00
parent ce34bae16a
commit 14775eb556
5 changed files with 80 additions and 8 deletions

View File

@@ -421,6 +421,13 @@ export default function setupAssociations() {
DaySell.belongsTo(FalukantUser, { foreignKey: 'sellerId', as: 'user' });
FalukantUser.hasMany(DaySell, { foreignKey: 'sellerId', as: 'daySells' });
// Produkt-Preishistorie (Zeitreihe für Preiskurven)
ProductPriceHistory.belongsTo(ProductType, { foreignKey: 'productId', as: 'productType' });
ProductType.hasMany(ProductPriceHistory, { foreignKey: 'productId', as: 'priceHistory' });
ProductPriceHistory.belongsTo(RegionData, { foreignKey: 'regionId', as: 'region' });
RegionData.hasMany(ProductPriceHistory, { foreignKey: 'regionId', as: 'productPriceHistory' });
Notification.belongsTo(FalukantUser, { foreignKey: 'userId', as: 'user' });
FalukantUser.hasMany(Notification, { foreignKey: 'userId', as: 'notifications' });

View File

@@ -0,0 +1,44 @@
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../../../utils/sequelize.js';
/**
* Preishistorie pro Produkt und Region (Zeitreihe für Preis-Graphen).
* Aktuell wird diese Tabelle noch nicht befüllt; sie dient nur als Grundlage.
*/
class ProductPriceHistory extends Model { }
ProductPriceHistory.init({
productId: {
type: DataTypes.INTEGER,
allowNull: false
},
regionId: {
type: DataTypes.INTEGER,
allowNull: false
},
price: {
type: DataTypes.DECIMAL(12, 2),
allowNull: false
},
recordedAt: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: sequelize.literal('CURRENT_TIMESTAMP')
}
}, {
sequelize,
modelName: 'ProductPriceHistory',
tableName: 'product_price_history',
schema: 'falukant_log',
timestamps: false,
underscored: true,
indexes: [
{
name: 'product_price_history_product_region_recorded_idx',
fields: ['product_id', 'region_id', 'recorded_at']
}
]
});
export default ProductPriceHistory;

View File

@@ -89,6 +89,7 @@ import Learning from './falukant/data/learning.js';
import Credit from './falukant/data/credit.js';
import DebtorsPrism from './falukant/data/debtors_prism.js';
import HealthActivity from './falukant/log/health_activity.js';
import ProductPriceHistory from './falukant/log/product_price_history.js';
// — Match3 Minigame —
import Match3Campaign from './match3/campaign.js';
@@ -239,6 +240,7 @@ const models = {
Credit,
DebtorsPrism,
HealthActivity,
ProductPriceHistory,
RegionDistance,
VehicleType,
Vehicle,

View File

@@ -2901,9 +2901,9 @@ class FalukantService extends BaseService {
}
async getGifts(hashedUserId) {
// 1) Mein User & Character
// 1) Mein aktiver Falukant-User & dessen aktueller Charakter
const user = await this.getFalukantUserByHashedId(hashedUserId);
const myChar = await FalukantCharacter.findOne({ where: { userId: user.id } });
const myChar = user.character;
if (!myChar) throw new Error('Character not found');
// 2) Beziehung finden und „anderen“ Character bestimmen
@@ -3520,12 +3520,10 @@ class FalukantService extends BaseService {
async baptise(hashedUserId, childId, firstName) {
try {
const falukantUser = await getFalukantUserOrFail(hashedUserId);
const parentCharacter = await FalukantCharacter.findOne({
where: {
userId: falukantUser.id,
},
});
// Nutze den aktuell aktiven Charakter (wie in getFalukantUserByHashedId definiert),
// statt „irgendeinen“ Charakter des Users per userId zu suchen.
const falukantUser = await this.getFalukantUserByHashedId(hashedUserId);
const parentCharacter = falukantUser.character;
if (!parentCharacter) {
throw new Error('Parent character not found');
}

View File

@@ -539,6 +539,27 @@ const syncDatabase = async () => {
console.warn('⚠️ relationship_change_log/Trigger konnten nicht sichergestellt werden:', e?.message || e);
}
// Preishistorie für Produkte (Zeitreihe) nur Schema/Struktur, noch ohne Logik
console.log("Ensuring falukant_log.product_price_history exists...");
try {
await sequelize.query(`
CREATE TABLE IF NOT EXISTS falukant_log.product_price_history (
id serial PRIMARY KEY,
product_id integer NOT NULL,
region_id integer NOT NULL,
price numeric(12,2) NOT NULL,
recorded_at timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
);
`);
await sequelize.query(`
CREATE INDEX IF NOT EXISTS product_price_history_product_region_recorded_idx
ON falukant_log.product_price_history (product_id, region_id, recorded_at);
`);
console.log("✅ product_price_history ist vorhanden.");
} catch (e) {
console.warn('⚠️ product_price_history konnte nicht sichergestellt werden:', e?.message || e);
}
// Vorab: Stelle kritische Spalten sicher, damit Index-Erstellung nicht fehlschlägt
console.log("Pre-ensure Taxi columns (traffic_light) ...");
try {