feat(falukant): enhance tax calculation and update messaging parameters
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s
- Updated the tax calculation logic in FalukantService to include character-based checks for political offices, improving accuracy in tax assessments. - Enhanced the MessagesDialog component to incorporate additional parameters such as satisfaction, threshold_percent, director_id, and director_character_id, providing more detailed notifications. - Added new localization entries for director resignation risk notifications in multiple languages, ensuring users receive clear and contextual information regarding director dynamics.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
async up(queryInterface, Sequelize) {
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE falukant_data.relationship_state
|
||||
ADD COLUMN IF NOT EXISTS marriage_satisfaction integer;
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
UPDATE falukant_data.relationship_state
|
||||
SET marriage_satisfaction = 55
|
||||
WHERE marriage_satisfaction IS NULL;
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE falukant_data.relationship_state
|
||||
ALTER COLUMN marriage_satisfaction SET DEFAULT 55;
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE falukant_data.relationship_state
|
||||
ALTER COLUMN marriage_satisfaction SET NOT NULL;
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'relationship_state_marriage_satisfaction_check'
|
||||
AND connamespace = 'falukant_data'::regnamespace
|
||||
) THEN
|
||||
ALTER TABLE falukant_data.relationship_state
|
||||
ADD CONSTRAINT relationship_state_marriage_satisfaction_check
|
||||
CHECK (marriage_satisfaction >= 0 AND marriage_satisfaction <= 100);
|
||||
END IF;
|
||||
END $$;
|
||||
`);
|
||||
},
|
||||
|
||||
async down(queryInterface, Sequelize) {
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE falukant_data.relationship_state
|
||||
DROP CONSTRAINT IF EXISTS relationship_state_marriage_satisfaction_check;
|
||||
`);
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
ALTER TABLE falukant_data.relationship_state
|
||||
DROP COLUMN IF EXISTS marriage_satisfaction;
|
||||
`);
|
||||
}
|
||||
};
|
||||
@@ -326,9 +326,16 @@ async function calcRegionalSellPrice(product, knowledgeFactor, regionId, worthPe
|
||||
async function getCumulativeTaxPercentWithExemptions(userId, regionId) {
|
||||
if (!regionId) return 0;
|
||||
if (await hasTitleTaxExempt(userId)) return 0;
|
||||
const character = await FalukantCharacter.findOne({
|
||||
where: { userId },
|
||||
attributes: ['id']
|
||||
});
|
||||
if (!character?.id) {
|
||||
return await getCumulativeTaxPercent(regionId);
|
||||
}
|
||||
// fetch user's political offices (active) and their region types
|
||||
const offices = await PoliticalOffice.findAll({
|
||||
where: { userId },
|
||||
where: { characterId: character.id },
|
||||
include: [{ model: PoliticalOfficeType, as: 'type', attributes: ['name'] }, { model: RegionData, as: 'region', include: [{ model: RegionType, as: 'regionType', attributes: ['labelTr'] }] }]
|
||||
});
|
||||
|
||||
|
||||
126
backend/sql/fix_schema_drift_falukant_compat.sql
Normal file
126
backend/sql/fix_schema_drift_falukant_compat.sql
Normal file
@@ -0,0 +1,126 @@
|
||||
-- Falukant Schema-Drift Hotfix (idempotent)
|
||||
-- Ziel: Kompatibilitaet zwischen aktuellem App-Schema und Legacy/Daemon-Queries.
|
||||
--
|
||||
-- Behebt:
|
||||
-- 1) falukant_data.character.highest_church_hierarchy_ever
|
||||
-- 2) falukant_predefine.firstname.label / lastname.label
|
||||
-- 3) falukant_predefine.political_office_benefit.political_office_type_id
|
||||
-- 4) falukant_type.title.tr (Alias zu label_tr)
|
||||
--
|
||||
-- Ausfuehrung:
|
||||
-- psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f backend/sql/fix_schema_drift_falukant_compat.sql
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 1) character.highest_church_hierarchy_ever
|
||||
ALTER TABLE IF EXISTS falukant_data."character"
|
||||
ADD COLUMN IF NOT EXISTS highest_church_hierarchy_ever INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
-- 2) firstname/lastname: label <-> name kompatibel halten
|
||||
ALTER TABLE IF EXISTS falukant_predefine.firstname
|
||||
ADD COLUMN IF NOT EXISTS label TEXT;
|
||||
|
||||
ALTER TABLE IF EXISTS falukant_predefine.lastname
|
||||
ADD COLUMN IF NOT EXISTS label TEXT;
|
||||
|
||||
UPDATE falukant_predefine.firstname
|
||||
SET label = COALESCE(label, name),
|
||||
name = COALESCE(name, label)
|
||||
WHERE label IS NULL OR name IS NULL;
|
||||
|
||||
UPDATE falukant_predefine.lastname
|
||||
SET label = COALESCE(label, name),
|
||||
name = COALESCE(name, label)
|
||||
WHERE label IS NULL OR name IS NULL;
|
||||
|
||||
-- 3) political_office_benefit: political_office_type_id <-> office_type_id
|
||||
ALTER TABLE IF EXISTS falukant_predefine.political_office_benefit
|
||||
ADD COLUMN IF NOT EXISTS political_office_type_id INTEGER;
|
||||
|
||||
UPDATE falukant_predefine.political_office_benefit
|
||||
SET political_office_type_id = COALESCE(political_office_type_id, office_type_id),
|
||||
office_type_id = COALESCE(office_type_id, political_office_type_id)
|
||||
WHERE political_office_type_id IS NULL OR office_type_id IS NULL;
|
||||
|
||||
-- FKs fuer beide Spalten absichern (nur falls fehlend)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'political_office_benefit_office_type_id_fkey'
|
||||
AND connamespace = 'falukant_predefine'::regnamespace
|
||||
) THEN
|
||||
ALTER TABLE falukant_predefine.political_office_benefit
|
||||
ADD CONSTRAINT political_office_benefit_office_type_id_fkey
|
||||
FOREIGN KEY (office_type_id)
|
||||
REFERENCES falukant_type.political_office_type(id)
|
||||
ON DELETE CASCADE;
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'political_office_benefit_political_office_type_id_fkey'
|
||||
AND connamespace = 'falukant_predefine'::regnamespace
|
||||
) THEN
|
||||
ALTER TABLE falukant_predefine.political_office_benefit
|
||||
ADD CONSTRAINT political_office_benefit_political_office_type_id_fkey
|
||||
FOREIGN KEY (political_office_type_id)
|
||||
REFERENCES falukant_type.political_office_type(id)
|
||||
ON DELETE CASCADE;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION falukant_predefine.sync_political_office_benefit_type_ids()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF NEW.office_type_id IS NULL THEN
|
||||
NEW.office_type_id := NEW.political_office_type_id;
|
||||
END IF;
|
||||
IF NEW.political_office_type_id IS NULL THEN
|
||||
NEW.political_office_type_id := NEW.office_type_id;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_sync_political_office_benefit_type_ids
|
||||
ON falukant_predefine.political_office_benefit;
|
||||
|
||||
CREATE TRIGGER trg_sync_political_office_benefit_type_ids
|
||||
BEFORE INSERT OR UPDATE ON falukant_predefine.political_office_benefit
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION falukant_predefine.sync_political_office_benefit_type_ids();
|
||||
|
||||
-- 4) title.tr <-> label_tr
|
||||
ALTER TABLE IF EXISTS falukant_type.title
|
||||
ADD COLUMN IF NOT EXISTS tr TEXT;
|
||||
|
||||
UPDATE falukant_type.title
|
||||
SET tr = COALESCE(tr, label_tr),
|
||||
label_tr = COALESCE(label_tr, tr)
|
||||
WHERE tr IS NULL OR label_tr IS NULL;
|
||||
|
||||
CREATE OR REPLACE FUNCTION falukant_type.sync_title_tr_label()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
IF NEW.tr IS NULL THEN
|
||||
NEW.tr := NEW.label_tr;
|
||||
END IF;
|
||||
IF NEW.label_tr IS NULL THEN
|
||||
NEW.label_tr := NEW.tr;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS trg_sync_title_tr_label
|
||||
ON falukant_type.title;
|
||||
|
||||
CREATE TRIGGER trg_sync_title_tr_label
|
||||
BEFORE INSERT OR UPDATE ON falukant_type.title
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION falukant_type.sync_title_tr_label();
|
||||
|
||||
COMMIT;
|
||||
@@ -364,6 +364,18 @@ export default {
|
||||
if (base.risk_percent !== undefined) {
|
||||
params.risk_percent = base.risk_percent;
|
||||
}
|
||||
if (base.satisfaction !== undefined) {
|
||||
params.satisfaction = base.satisfaction;
|
||||
}
|
||||
if (base.threshold_percent !== undefined) {
|
||||
params.threshold_percent = base.threshold_percent;
|
||||
}
|
||||
if (base.director_id !== undefined) {
|
||||
params.director_id = base.director_id;
|
||||
}
|
||||
if (base.director_character_id !== undefined) {
|
||||
params.director_character_id = base.director_character_id;
|
||||
}
|
||||
if (base.affection !== undefined) {
|
||||
params.affection = base.affection;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
"notifications": {
|
||||
"notify_election_created": "Giskedyul ang usa ka bag-ong eleksiyon.",
|
||||
"notify_office_filled": "Na puno ang usa ka politikal nga opisina.",
|
||||
"director": {
|
||||
"resignation_risk_high": "Taas ang risgo nga mubiyaa ang direktor: risgo {risk_percent}% (threshold {threshold_percent}%). Karon nga satisfaction {satisfaction}."
|
||||
},
|
||||
"director_death": "Namatay si {characterName} sa edad nga {ageYears}. Isip amo, kinahanglan kang magtudlo og bag-ong direktor.{regionLabel}{spouses}{children}{lovers}",
|
||||
"relationship_death": "Namatay si {characterName} sa edad nga {ageYears}.{regionLabel}{spouses}{children}{lovers}",
|
||||
"child_death": "Namatay ang imong anak nga si {characterName} sa edad nga {ageYears}.{regionLabel}",
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
"notifications": {
|
||||
"notify_election_created": "Es wurde eine neue Wahl ausgeschrieben.",
|
||||
"notify_office_filled": "Ein politisches Amt wurde neu besetzt.",
|
||||
"director": {
|
||||
"resignation_risk_high": "Hohe Kündigungsgefahr bei einem Direktor: Risiko {risk_percent}% (Schwelle {threshold_percent}%). Zufriedenheit aktuell {satisfaction}."
|
||||
},
|
||||
"director_death": "{characterName} ist im Alter von {ageYears} Jahren verstorben. Als Arbeitgeber musst du die Direktion neu besetzen.{regionLabel}{spouses}{children}{lovers}",
|
||||
"relationship_death": "{characterName} ist im Alter von {ageYears} Jahren verstorben.{regionLabel}{spouses}{children}{lovers}",
|
||||
"child_death": "Dein Kind {characterName} ist im Alter von {ageYears} Jahren verstorben.{regionLabel}",
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
"notifications": {
|
||||
"notify_election_created": "A new election has been scheduled.",
|
||||
"notify_office_filled": "A political office has been filled.",
|
||||
"director": {
|
||||
"resignation_risk_high": "High resignation risk for a director: risk {risk_percent}% (threshold {threshold_percent}%). Current satisfaction {satisfaction}."
|
||||
},
|
||||
"director_death": "{characterName} died at the age of {ageYears}. As employer you need to appoint a new director.{regionLabel}{spouses}{children}{lovers}",
|
||||
"relationship_death": "{characterName} died at the age of {ageYears}.{regionLabel}{spouses}{children}{lovers}",
|
||||
"child_death": "Your child {characterName} died at the age of {ageYears}.{regionLabel}",
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
"notifications": {
|
||||
"notify_election_created": "Se ha convocado una nueva elección.",
|
||||
"notify_office_filled": "Se ha cubierto un cargo político.",
|
||||
"director": {
|
||||
"resignation_risk_high": "Alto riesgo de renuncia de un director: riesgo {risk_percent}% (umbral {threshold_percent}%). Satisfacción actual {satisfaction}."
|
||||
},
|
||||
"director_death": "{characterName} ha fallecido a la edad de {ageYears} años. Como empleador debes nombrar un nuevo director.{regionLabel}{spouses}{children}{lovers}",
|
||||
"relationship_death": "{characterName} ha fallecido a la edad de {ageYears} años.{regionLabel}{spouses}{children}{lovers}",
|
||||
"child_death": "Tu hijo/a {characterName} ha fallecido a la edad de {ageYears} años.{regionLabel}",
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
"notifications": {
|
||||
"notify_election_created": "Une nouvelle élection a été déclenchée.",
|
||||
"notify_office_filled": "Une fonction politique a été pourvue.",
|
||||
"director": {
|
||||
"resignation_risk_high": "Risque élevé de démission d’un directeur : risque {risk_percent}% (seuil {threshold_percent}%). Satisfaction actuelle {satisfaction}."
|
||||
},
|
||||
"director_death": "{characterName} est décédé à l'âge de {ageYears}. En tant qu'employeur, vous devez remplir le conseil d'administration.{regionLabel}{spouses}{children}{lovers}",
|
||||
"relationship_death": "{characterName} est décédé à l'âge de {ageYears}.{regionLabel}{spouses}{children}{lovers}",
|
||||
"child_death": "Votre enfant {characterName} est décédé à l'âge de {ageYears}.{regionLabel}",
|
||||
|
||||
Reference in New Issue
Block a user