Initial Commit Fix
This commit is contained in:
parent
e2e0204c12
commit
095cbd6187
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const AdminService = require('../../services/AdminService');
|
const AdminService = require('../../services/admin/AdminService');
|
||||||
|
|
||||||
class AdminUserController {
|
class AdminUserController {
|
||||||
static async getUserStats(req, res) {
|
static async getUserStats(req, res) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const pidusage = require('pidusage');
|
const pidusage = require('pidusage');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const AdminService = require('../../services/AdminService');
|
const AdminService = require('../../services/admin/AdminService');
|
||||||
|
|
||||||
class ServerStatusController {
|
class ServerStatusController {
|
||||||
static async getStatus(req, res) {
|
static async getStatus(req, res) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const EmailVerificationRepository = require('../../repositories/EmailVerificationRepository');
|
const EmailVerificationRepository = require('../../repositories/email/EmailVerificationRepository');
|
||||||
const EmailVerificationService = require('../../services/EmailVerificationService');
|
const EmailVerificationService = require('../../services/email/EmailVerificationService');
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class EmailVerificationController {
|
class EmailVerificationController {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const UserRepository = require('../../repositories/UserRepository');
|
const UserRepository = require('../../repositories/user/UserRepository');
|
||||||
const { s3 } = require('../../utils/exoscaleUploader');
|
const { s3 } = require('../../utils/exoscaleUploader');
|
||||||
const { GetObjectCommand } = require('@aws-sdk/client-s3');
|
const { GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const UserSettingsRepository = require('../../repositories/UserSettingsRepository');
|
const UserSettingsRepository = require('../../repositories/settings/UserSettingsRepository');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- import logger
|
const { logger } = require('../../middleware/logger'); // <-- import logger
|
||||||
|
|
||||||
class UserSettingsController {
|
class UserSettingsController {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const UserStatusRepository = require('../../repositories/UserStatusRepository');
|
const UserStatusRepository = require('../../repositories/user/UserRepository');
|
||||||
const UserStatusService = require('../../services/UserStatusService'); // Add this import
|
const UserStatusService = require('../../services/status/UserStatusService');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- import logger
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserStatusController {
|
class UserStatusController {
|
||||||
static async getStatus(req, res) {
|
static async getStatus(req, res) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const CompanyStampService = require('../../services/CompanyStampService');
|
const CompanyStampService = require('../../services/stamp/company/CompanyStampService');
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
exports.upload = async (req, res) => {
|
exports.upload = async (req, res) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const DocumentTemplateService = require('../../services/DocumentTemplateService');
|
const DocumentTemplateService = require('../../services/template/DocumentTemplateService');
|
||||||
const ContractUploadService = require('../../services/ContractUploadService');
|
const ContractUploadService = require('../../services/contracts/ContractUploadService');
|
||||||
const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');
|
const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
||||||
const PDFDocument = require('pdfkit');
|
const PDFDocument = require('pdfkit');
|
||||||
@ -8,10 +8,10 @@ const puppeteer = require('puppeteer');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const DEBUG_PDF_FILES = !!process.env.DEBUG_PDF_FILES;
|
const DEBUG_PDF_FILES = !!process.env.DEBUG_PDF_FILES;
|
||||||
const db = require('../../database/database'); // add DB access for fetching personal_profiles
|
const db = require('../../database/database');
|
||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- FIXED
|
const { logger } = require('../../middleware/logger');
|
||||||
const CompanyStampService = require('../../services/CompanyStampService'); // ensure present
|
const CompanyStampService = require('../../services/stamp/company/CompanyStampService');
|
||||||
|
|
||||||
// Ensure debug directory exists and helper to save files
|
// Ensure debug directory exists and helper to save files
|
||||||
function ensureDebugDir() {
|
function ensureDebugDir() {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const CompanyDocumentService = require('../../services/CompanyDocumentService');
|
const CompanyDocumentService = require('../../services/documents/company/CompanyDocumentService');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- import logger
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class CompanyDocumentController {
|
class CompanyDocumentController {
|
||||||
static async uploadCompanyId(req, res) {
|
static async uploadCompanyId(req, res) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const ContractUploadService = require('../../services/ContractUploadService');
|
const ContractUploadService = require('../../services/contracts/ContractUploadService');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- import logger
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class ContractUploadController {
|
class ContractUploadController {
|
||||||
static async uploadPersonalContract(req, res) {
|
static async uploadPersonalContract(req, res) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const PersonalDocumentService = require('../../services/PersonalDocumentService');
|
const PersonalDocumentService = require('../../services/documents/personal/PersonalDocumentService');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- import logger
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class PersonalDocumentController {
|
class PersonalDocumentController {
|
||||||
static async uploadPersonalId(req, res) {
|
static async uploadPersonalId(req, res) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const UserDocumentRepository = require('../../repositories/UserDocumentRepository');
|
const UserDocumentRepository = require('../../repositories/documents/UserDocumentRepository');
|
||||||
const { s3 } = require('../../utils/exoscaleUploader');
|
const { s3 } = require('../../utils/exoscaleUploader');
|
||||||
const { GetObjectCommand } = require('@aws-sdk/client-s3');
|
const { GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
const LoginService = require('../../services/LoginService');
|
const LoginService = require('../../services/login/LoginService');
|
||||||
const MailService = require('../../services/MailService');
|
const MailService = require('../../services/email/MailService');
|
||||||
const { checkAndIncrementRateLimit } = require('../../middleware/rateLimiter');
|
const { checkAndIncrementRateLimit } = require('../../middleware/rateLimiter');
|
||||||
const { logger } = require('../../middleware/logger'); // <-- import logger
|
const { logger } = require('../../middleware/logger');
|
||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const db = require('../../database/database'); // Use singleton pool
|
const db = require('../../database/database');
|
||||||
|
|
||||||
class LoginController {
|
class LoginController {
|
||||||
static async login(req, res) {
|
static async login(req, res) {
|
||||||
@ -1,9 +1,9 @@
|
|||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const MailService = require('../../services/MailService');
|
const MailService = require('../../services/email/MailService');
|
||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const PersonalUserRepository = require('../../repositories/PersonalUserRepository');
|
const PersonalUserRepository = require('../../repositories/user/personal/PersonalUserRepository');
|
||||||
const CompanyUserRepository = require('../../repositories/CompanyUserRepository');
|
const CompanyUserRepository = require('../../repositories/user/company/CompanyUserRepository');
|
||||||
const PasswordResetRepository = require('../../repositories/PasswordResetRepository');
|
const PasswordResetRepository = require('../../repositories/passwordReset/PasswordResetRepository');
|
||||||
const User = require('../../models/User');
|
const User = require('../../models/User');
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const PermissionService = require('../../services/PermissionService');
|
const PermissionService = require('../../services/permissions/PermissionService');
|
||||||
const PermissionRepository = require('../../repositories/PermissionRepository');
|
const PermissionRepository = require('../../repositories/permissions/PermissionRepository');
|
||||||
|
|
||||||
class PermissionController {
|
class PermissionController {
|
||||||
static async list(req, res) {
|
static async list(req, res) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const CompanyProfileService = require('../../services/CompanyProfileService');
|
const CompanyProfileService = require('../../services/profile/company/CompanyProfileService');
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class CompanyProfileController {
|
class CompanyProfileController {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const PersonalProfileService = require('../../services/PersonalProfileService');
|
const PersonalProfileService = require('../../services/profile/personal/PersonalProfileService');
|
||||||
const PersonalUserRepository = require('../../repositories/PersonalUserRepository');
|
const PersonalUserRepository = require('../../repositories/user/personal/PersonalUserRepository');
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class PersonalProfileController {
|
class PersonalProfileController {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const ReferralService = require('../../services/ReferralService');
|
const ReferralService = require('../../services/referral/ReferralService');
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class ReferralRegistrationController {
|
class ReferralRegistrationController {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const ReferralService = require('../../services/ReferralService'); // <-- use unified service
|
const ReferralService = require('../../services/referral/ReferralService'); // <-- use unified service
|
||||||
const { logger } = require('../../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
// Helper to get frontend URL without trailing slash, no localhost fallback
|
// Helper to get frontend URL without trailing slash, no localhost fallback
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const CompanyUserService = require('../../services/CompanyUserService');
|
const CompanyUserService = require('../../services/user/company/CompanyUserService');
|
||||||
const { logger } = require('../../middleware/logger'); // add logger import
|
const { logger } = require('../../middleware/logger'); // add logger import
|
||||||
|
|
||||||
class CompanyRegisterController {
|
class CompanyRegisterController {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const PersonalUserService = require('../../services/PersonalUserService');
|
const PersonalUserService = require('../../services/user/personal/PersonalUserService');
|
||||||
const { logger } = require('../../middleware/logger'); // add logger import
|
const { logger } = require('../../middleware/logger'); // add logger import
|
||||||
|
|
||||||
class PersonalRegisterController {
|
class PersonalRegisterController {
|
||||||
|
|||||||
209
debug-pdf/template_1_html_full.html
Normal file
209
debug-pdf/template_1_html_full.html
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>VERTRIEBSPARTNER / BUSINESSPARTNER / AFFILIATE - VERTRAG</title>
|
||||||
|
<style>
|
||||||
|
/* PDF friendly page setup */
|
||||||
|
@page { size:A4; margin:15mm 12mm 18mm 12mm; }
|
||||||
|
body { font-family:Arial,Helvetica,sans-serif; line-height:1.4; font-size:13px; counter-reset: page; margin:0; }
|
||||||
|
h1 { text-align:center; font-size:18px; margin:0 0 8px; }
|
||||||
|
h2 { margin:16px 0 6px; font-size:13px; }
|
||||||
|
.page { page-break-after:always; padding:12px 20px 18px; }
|
||||||
|
.page:last-child { page-break-after:auto; }
|
||||||
|
.page-header { display:flex; justify-content:flex-end; font-size:0.65em; counter-increment:page; }
|
||||||
|
.page-header:after { content:"Seite " counter(page); }
|
||||||
|
.meta-info { border:1px solid #000; padding:8px 12px; margin:12px 0 25px; font-size:0.9em; }
|
||||||
|
.meta-info table { width:100%; border-collapse:collapse; }
|
||||||
|
.meta-info td { padding:3px 6px; vertical-align:top; border-bottom:1px solid #ccc; }
|
||||||
|
.meta-info td:first-child { font-weight:bold; width:28%; white-space:nowrap; }
|
||||||
|
.meta-info tr:last-child td { border-bottom:0; }
|
||||||
|
/* Unified signatures */
|
||||||
|
.signatures { display:flex; gap:30px; margin-top:38px; }
|
||||||
|
.signature { flex:1; text-align:center; }
|
||||||
|
/* Added: extra space below company stamp so date sits clearly underneath */
|
||||||
|
.signature-company .sig-image { margin-bottom:22px !important; }
|
||||||
|
.signature-company .sig-date { margin-top:0 !important; }
|
||||||
|
.sig-block { display:flex; flex-direction:column; align-items:center; gap:6px; min-height:120px; }
|
||||||
|
.sig-image { display:block; max-width:180px !important; max-height:70px !important; height:auto !important; margin:0 auto 6px; }
|
||||||
|
.sig-date { margin-top:4px; display:block; }
|
||||||
|
.page-header-block{display:flex;flex-direction:column;align-items:flex-end;gap:3px;margin-bottom:6px;}
|
||||||
|
.print-date{font-size:0.7em;}
|
||||||
|
@media print {
|
||||||
|
body { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
|
||||||
|
}
|
||||||
|
/* ADDED: full size Profit Planet signature */
|
||||||
|
.pp-stamp,
|
||||||
|
.pp-stamp img {
|
||||||
|
max-width:none !important;
|
||||||
|
max-height:none !important;
|
||||||
|
width:auto !important;
|
||||||
|
height:auto !important;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<div class="page-header-block">
|
||||||
|
<div class="page-header"></div>
|
||||||
|
<div class="print-date">Erstellt am: {{currentDate}}</div>
|
||||||
|
</div>
|
||||||
|
<h1>VERTRIEBSPARTNER / BUSINESSPARTNER / AFFILIATE - VERTRAG</h1>
|
||||||
|
<p style="text-align:center;margin:0 0 6px;">idF 21.05.2025</p>
|
||||||
|
<p>abgeschlossen zwischen</p>
|
||||||
|
<p>Profit Planet GmbH (kurz PROFIT PLANET)<br>FN 649474i<br>Liebenauer Hauptstraße 82c<br>A-8041 Graz</p>
|
||||||
|
<p>und</p>
|
||||||
|
<p>Vertriebspartner / Businesspartner / Affiliate (kurz VP)</p>
|
||||||
|
<div class="meta-info">
|
||||||
|
<table class="meta-grid">
|
||||||
|
<tr>
|
||||||
|
<td>Vertriebspartner</td>
|
||||||
|
<td>{{fullName}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Adresse</td>
|
||||||
|
<td>{{address}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>PLZ / Ort</td>
|
||||||
|
<td>{{zip_code}} {{city}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Vollständige Adresse</td>
|
||||||
|
<td>{{fullAddress}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>E-Mail / Telefon</td>
|
||||||
|
<td>{{email}} / {{phone}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<h2>1. Präambel und Vertragsgegenstand</h2>
|
||||||
|
<p>1.1. Dieser Vertrag regelt die Zusammenarbeit zwischen PROFIT PLANET und VP als Grundlage einer fairen, langfristigen und erfolgreichen Kooperation. Die VP unterstützen einander im Sinne der Ziele der Zusammenarbeit und unterrichten sich gegenseitig über alle Vorgänge, die für ihre Leistungen im Rahmen der Kooperation von Interesse sind.</p>
|
||||||
|
<p>1.2. PROFIT PLANET bietet über ein Vertriebspartner / Businesspartner / Affiliate-Netzwerk den Vertrieb verschiedener Dienstleistungen und Produkte, vornehmlich aus den Bereichen Nachhaltigkeit, Energie, Handel sowie Consulting und Coaching an.</p>
|
||||||
|
<p>1.3. Der VP vermittelt die jeweiligen Dienstleistungen, Produkte oder qualifizierten Leads, die zu einem Abschluss führen, und erhält dafür eine Provision. Für die Tätigkeit als VP ist es nicht erforderlich, weitere VP zu werben.</p>
|
||||||
|
<p>1.4. Der VP ist berechtigt, weitere Vertriebspartner / Businesspartner / Affiliate für den Vertrieb der Dienstleistungen und Produkte zu gewinnen. Für die Vermittlung und Betreuung der von ihm akquirierten Vertriebspartner / Businesspartner / Affiliate erhält der werbende VP eine Provision, die sich aus den erwirtschafteten Umsätzen der geworbenen VP ermittelt. Die Höhe der Provision ergibt sich aus der Provisionsübersicht.</p>
|
||||||
|
<p>1.5. Die Vertragsabschlüsse kommen nur zwischen dem Endkunden und dem jeweiligen Dienstleister und/oder Produktgeber (Energieversorgungs-, Handels-, Dienstleistungs- oder Coachingunternehmen) zustande, ohne dass dadurch eine Vertragsbeziehung zwischen dem VP und dem Endkunden entsteht. Ein Anspruch auf Abschluss des jeweiligen Vertrags seitens des Endkunden gegenüber PROFIT PLANET oder dem VP entsteht nicht; der Vertragsabschluss ist von der Annahme des entsprechenden Antrags durch den Dienstleister bzw. Produktgeber abhängig. PROFIT PLANET hat darauf keinen Einfluss.</p>
|
||||||
|
<p>1.6. PROFIT PLANET behält sich vor, die angebotenen Produkte zurückzuziehen, zu ändern, neue hinzuzufügen oder sonstige Anpassungen des Produktangebots vorzunehmen. PROFIT PLANET wird den VP über Änderungen von Produkten oder Tarifen nach Maßgabe der Möglichkeiten rechtzeitig vor Wirksamkeit der Änderungen informieren.</p>
|
||||||
|
<p>1.7. Die genauen Produktbestandteile und Konditionen ergeben sich aus dem jeweiligen Produktpartnerinformationsblatt, welches auf der Online-Plattform hinterlegt wird.</p>
|
||||||
|
<p>1.8. PROFIT PLANET ist berechtigt, nach eigenem Ermessen andere Personen und Unternehmen mit der Vermittlung von Produkten und Dienstleistungen von PROFIT PLANET bzw. Produktpartnern von PROFIT PLANET zu beauftragen. Es bestehen grundsätzlich keine Alleinvermittlungsaufträge und keine Exklusivität.</p>
|
||||||
|
|
||||||
|
<h2>2. Vertriebspartner / Businesspartner / Affiliate werden</h2>
|
||||||
|
<p>2.1. Kapitalgesellschaften, Personengesellschaften und volljährige natürliche Personen können Vertriebspartner / Businesspartner / Affiliate des PROFIT PLANET werden; pro Entität ist die Registrierung nur eines VP-Vertrags vorgesehen. Natürliche Personen, die bloß als Verbraucher handeln (wollen), können nicht Vertriebspartner / Businesspartner / Affiliate von PROFIT PLANET werden.</p>
|
||||||
|
<p>2.2. Kapitalgesellschaften müssen ihrem VP-Antrag die Firmenbuchnummer und gegebenenfalls die Umsatzsteuer-Identifikationsnummer (UID) beilegen. Der Antrag muss von allen Zeichnungsbereichten der Gesellschaft derart gezeichnet werden, dass eine rechtwirksame Vertretung sichergestellt ist. Die Gesellschafter haften gegenüber PROFIT PLANET jeweils persönlich für das Verhalten der Gesellschaft.</p>
|
||||||
|
<p>2.3. Absatz 2.2 gilt inhaltsgemäß auch für Personengesellschaften.</p>
|
||||||
|
<p>2.4. Der VP ist verpflichtet, Änderungen seiner unternehmens- oder personenbezogenen Daten unverzüglich an PROFIT PLANET zu melden.</p>
|
||||||
|
<p>2.5. Für die Verwendung des Online-Systems gelten die allgemeinen Geschäftsbedingungen.</p>
|
||||||
|
<p>2.6. PROFIT PLANET kann Vertriebspartner / Businesspartner / Affiliate ohne Angabe von Gründen ablehnen.</p>
|
||||||
|
|
||||||
|
<h2>3. Leistungen / Pflichten des VP</h2>
|
||||||
|
<p>3.1. Der VP handelt unabhängig als selbständiger Unternehmer, er ist weder Arbeitnehmer noch Handelsvertreter oder Makler von PROFIT PLANET. Er ist bei der Vermittlung von Produktverträgen eigenverantwortlich tätig, handelt abgesehen von den Pflichten aus diesem Vertrag frei von Weisungen und ist nicht mit der ständigen Vermittlung von Geschäften betraut. Es bestehen seitens PROFIT PLANET keine Umsatzvorgaben und keine Abnahme- oder Vertriebspflichten. Der VP trägt alle mit der Kundenakquisition verbundenen Kosten und Risiken selbst und verwendet eigene Betriebsmittel. Er stellt im geschäftlichen Verkehr klar, dass er nicht im Auftrag oder im Namen von PROFIT PLANET handelt, sondern als unabhängiger Vertriebspartner / Businesspartner / Affiliate.</p>
|
||||||
|
<p>3.2. Der VP betreibt sein Unternehmen mit der Sorgfalt eines ordentlichen Kaufmanns und ist für die Einhaltung aller gesetzlichen sowie der steuer- und sozialrechtlichen Vorgaben selbst verantwortlich.</p>
|
||||||
|
<p>3.3. Der VP hält sich insbesondere auch an das Wettbewerbsrecht und nimmt Abstand von ungenehmigter, irreführender oder sonst unlauterer Werbung. Der VP verpflichtet sich auch, falsche oder irreführende Aussagen über Dienstleistungen, Produkte und Vertriebssystem der PROFIT PLANET zu unterlassen.</p>
|
||||||
|
<p>3.4. Grundsätzlich steht es dem VP frei, Produkte / Dienstleistungen auch für andere Unternehmen zu vertreiben. Falls es allerdings in der Zusammenarbeit mit einem anderen Dienstleister oder Produktgeber in räumlicher oder zeitlicher Nähe zu Überschneidungen im Vertrieb, insbesondere bei Terminisierungen, Promotion-Auftritten (POS) oder anderen dienstleistungs- oder produktspezifischen Werbetätigkeiten kommen, so wäre dies nur nach ausdrücklicher Zustimmung durch PROFIT PLANET zulässig.</p>
|
||||||
|
<p>3.5. Beim Abschluss von Kundenverträgen ist der VP verpflichtet, die von PROFIT PLANET zur Verfügung gestellten Originalunterlagen (zB Antragsformulare, AGB, sonstige Unterlagen der Dienstleister oder Produktgeber) in der jeweils aktuellen Version zu verwenden und dem Kunden bei Vertragsabschluss vorzulegen bzw. auszuhändigen. Die Originalunterlagen sind durch den VP nicht zu verändern, missbräuchliche Verwendung ist zu verhindern.</p>
|
||||||
|
<p>3.6. Kundenverträge in Papierform sind vom VP unverzüglich, spätestens jedoch binnen 1 Woche nach Aufforderung durch PROFIT PLANET oder den Produktgeber an PROFIT PLANET auszuhändigen.</p>
|
||||||
|
<p>3.7. Sämtliche Präsentations-, Werbe- und Schulungsmaterialien sowie label von PROFIT PLANET sind urheberrechtlich geschützt und dürfen ohne ausdrückliches Einverständnis von PROFIT PLANET weder ganz noch teilweise vervielfältigt, verbreitet oder öffentlich zugänglich gemacht werden. Die Herstellung, Verwendung und Verbreitung eigener Werbemittel, Schulungsmaterialien oder Produktbroschüren ist nur nach schriftlicher Genehmigung und Freigabe durch PROFIT PLANET gestattet.</p>
|
||||||
|
<p>3.8. Der VP ist während der Dauer dieser Vereinbarung und für die Dauer von 36 Monaten nach Beendigung dieses Vertrags aus welchem Grund immer, nicht berechtigt, unmittelbar selbst bzw. mittelbar über Dritte Kunden von PROFIT PLANET und ihrer Produktpartner, einschließlich der vom VP vermittelten Endkunden, durch direkte Ansprache abzuwerben. Als Abwerben gilt jede Form des direkten Herantretens an den Kunden mit der Absicht, ihn zum Wechsel zu einem anderen Energieversorgungs-, Dienstleistungs-, Handels-, und/oder Coachingunternehmen zu bewegen (beispielsweise etwa durch Anrufe beim Kunden, Direktmailing mit Absicht der Abwerbung, Haustürgeschäfte etc.).</p>
|
||||||
|
<h2>4. Geheimhaltung</h2>
|
||||||
|
<p>4.1. Der VP verpflichtet sich, Geschäfts- und Betriebsgeheimnisse und sonstige vertrauliche Informationen von PROFIT PLANET und dessen Struktur, Geschäftspartner, Vertriebspartner / Businesspartner / Affiliate, Produktgeber, Provisionen und Endkunden unter äußerster Geheimhaltung zu behandeln und zu verwahren und diese Daten nur nach erfolgter schriftlicher Zustimmung durch den PROFIT PLANET an Dritte weiterzugeben.</p>
|
||||||
|
<p>4.2. Diese Verpflichtung gilt auch für Mitarbeiter und Unter-Vertriebspartner / Businesspartner / Affiliate des VP. Der VP hat für das Verhalten allfälliger Erfüllungsgehilfen und/oder Subpartner einzustehen.</p>
|
||||||
|
<p>4.3. Zu den Geschäftsgeheimnissen gehören insbesondere auch Informationen zu internen Betriebsabläufen, Provisionen und Provisionsstrukturen, Produkt- und Preiskalkulationen, Vertriebspartner / Businesspartner / Affiliate-strukturen und -aktivitäten.</p>
|
||||||
|
<p>4.4. Dem VP ist es nicht gestattet, auf Presseanfragen zu PROFIT PLANET, dessen Provisionspläne, Produkte oder andere Leistungen zu antworten. Presseanfragen sind immer an PROFIT PLANET weiterzuleiten.</p>
|
||||||
|
<h2>5. Datenschutz</h2>
|
||||||
|
<p>5.1. Die Vertragspartner sind verpflichtet, die gesetzlichen Datenschutzbestimmungen vollumfänglich einzuhalten. Für Verstöße gegen datenschutzrechtliche Schutzbestimmungen haftet ausschließlich der jeweils die Bestimmung verletzende Vertragspartner, dieser wird den schuldlos handelnden Vertragspartner von allen entsprechenden Ansprüchen freistellen und schad- und klaglos halten.</p>
|
||||||
|
<p>5.2. Im Regelfall ist der VP ist hinsichtlich der Daten der von ihm vermittelten Endkunden und Akquisitionskontakte Subauftragsverarbeiter im Sinne der Datenschutzgesetze (DSG, DSGVO); PROFIT PLANET ist Auftragsverarbeiter im Sinne der DSGVO. Soweit durch die gesetzlichen Bestimmungen vorgesehen, werden zu dieser Vereinbarung entsprechende datenschutzrechtliche Zusatzverträge abgeschlossen.</p>
|
||||||
|
<p>5.3. PROFIT PLANET ist bezüglich der Daten des VP auf Datenschutz verpflichtet. Die Datenschutzerklärung ist Online jederzeit abrufbar.</p>
|
||||||
|
<h2>6. VP-Schutz</h2>
|
||||||
|
<p>6.1. Ein neu geworbener VP wird in die Struktur desjenigen VP zugewiesen, der ihn geworben hat (VP-Schutz). Wenn mehrere VP denselben VP neu melden, wird seitens PROFIT PLANET nur die zuerst erfolgte Meldung berücksichtigt, wobei das Eingangsdatum des Registrierungsantrags bei PROFIT PLANET für die Zuteilung maßgeblich ist.</p>
|
||||||
|
<p>6.2. Der meldende VP ist verantwortlich dafür, die Daten des geworbenen VP vollständig und ordentlich zu übermitteln. PROFIT PLANET ist berechtigt, die Daten eines geworbenen VP aus ihrem System zu löschen, wenn von diesem innerhalb einer angemessenen Frist keine Umsätze oder Rückmeldungen kommen.</p>
|
||||||
|
<p>6.3. Ein Wechsel von der Struktur eines VP in die eines anderen ist grundsätzlich ausgeschlossen und nur ausnahmsweise möglich, wenn der wechselwillige VP nachweist, dass der in der Struktur über ihm stehende VP versucht hat, ihn zu einem gesetzes- oder vertragswidrigen Verhalten zu veranlassen oder sonst schwerwiegende Vorfälle die weitere Zusammenarbeit in der Struktur dieses VP untragbar machen. Über einen entsprechenden schriftlichen Antrag entscheidet PROFIT PLANET nach freiem Ermessen.</p>
|
||||||
|
<p>6.4. Ein VP, der innerhalb der letzten 12 Monate bereits einen VP-Vertrag mit PROFIT PLANET hatte, kann nicht geworben werden.</p>
|
||||||
|
<p>6.5. Eine Umgehung des VP-Schutzes etwa durch Verwendung der Namen von Strohnamen, -personen oder -firmen ist untersagt.</p>
|
||||||
|
<p>6.6. PROFIT PLANET räumt ihren VP ausdrücklich keinen Gebietsschutz ein. Alle VP können europaweit ohne Einschränkungen tätig sein.</p>
|
||||||
|
<h2>7. Provision</h2>
|
||||||
|
<p>7.1. Für jedes vom VP erfolgreich vermittelte Vertragsverhältnis zwischen Produktgeber und Endkunden erwirbt der VP Anspruch auf Provision als Bearbeitungs- und Aufwandspauschale</p>
|
||||||
|
<p>7.2. Die Höhe der Provision richtet sich nach der jeweils aktuell gültigen Provisionsübersicht laut Marketingkonzept. Die jeweils gültige Fassung dieser Provisionsübersicht ist jederzeit auf der Website von PROFIT PLANET (www.profit-planet.com) im internen Bereich abrufbar, einsehbar, downloadbar und kann dort auch auf Anfrage zur Verfügung gestellt werden. Änderungen der Provisionsübersicht werden dem VP rechtzeitig bekannt gegeben. Es gelten jeweils die zum Zeitpunkt der Vermittlung gültigen Provisionssätze.</p>
|
||||||
|
<p>7.3. Als erfolgreiche Vermittlung im Sinne dieses Vertrages gilt, wenn das Vertragsverhältnis zwischen Endkunden und Produktpartner tatsächlich zustande gekommen ist. Insbesondere entsteht kein Provisionsanspruch, wenn</p>
|
||||||
|
<ul>
|
||||||
|
<li>der Kunde von seinen Widerrufs- oder Rücktrittsrechten Gebrauch macht,</li>
|
||||||
|
<li>der Vertrag rechtswirksam angefochten wird,</li>
|
||||||
|
<li>der Kunde vom Dienstleister oder Produktpartner aus welchem Grund auch immer nicht angenommen wird,</li>
|
||||||
|
<li>fehlerhafte oder unvollständige Kundenanträge eingereicht werden,</li>
|
||||||
|
<li>der Vertrag widerrechtlich zustande gekommen ist oder</li>
|
||||||
|
<li>der Dienstleister oder Produktgeber die Auszahlung der Provision an PROFIT PLANET aus Gründen, die nicht von PROFIT PLANET zu verantworten sind, verweigert.</li>
|
||||||
|
</ul>
|
||||||
|
<p>7.4. Anspruch auf Auszahlung der Provision entsteht gegenüber PROFIT PLANET grundsätzlich erst dann, wenn die Zahlungen seitens des Geschäftspartners / Produktgebers bei PROFIT PLANET eingelangt sind und alle sonstigen Auszahlungsvoraussetzungen vorliegen. Der VP nimmt zur Kenntnis, dass die exakten Zahlungsmodalitäten bei den verschiedenen Dienstleistern oder Produktgebern voneinander abweichen können und PROFIT PLANET diese Unterschiede bei der Auszahlung berücksichtigt. Die unterschiedlichen Zeitspannen divergieren je nach Partnerunternehmen derzeit durchschnittlich zwischen 30 bis 100 Tage. Die genauen Anforderungen und Konditionen ergeben sich aus dem jeweiligen Produktpartnerinformationsblatt und dem Marketingkonzept.</p>
|
||||||
|
<p>7.5. Die Auszahlung durch PROFIT PLANET erfolgt einmal monatlich, ungefähr um den 20. des auf den Zahlungseingang bei PROFIT PLANET folgenden Monats. Die Auszahlung erfolgt bargeldlos per Überweisung auf das vom VP genannte Konto. PROFIT PLANET kann Zahlungen bis zu einer Höhe von EUR 100,00 von der Auszahlung ausschließen (Mindestauszahlungshöhe); die nicht ausbezahlten Provisionsansprüche werden auf dem Provisionskonto des VP rechnerisch fortgeführt und im Folgemonat nach Erreichen der Mindestauszahlungshöhe ausbezahlt. Beträge unterhalb der Mindestauszahlungshöhe werden einmal jährlich zur Auszahlung gebracht.</p>
|
||||||
|
<p>7.6. Der Provisionsanspruch entfällt rückwirkend, wenn PROFIT PLANET, Provisionen an einen Produktgeber zurückzahlen muss, etwa weil ein Kunde den Vertrag widerruft oder andere Ausschlusskriterien seitens des Produktgebers vorliegen (Stornohaftung etc.). PROFIT PLANET ist berechtigt, Forderungen, die dem PROFIT PLANET gegen den VP zustehen, mit dessen Provisionsansprüchen ganz oder teilweise aufzurechnen.</p>
|
||||||
|
<p>7.7. Mit dieser Provision sind sämtliche Tätigkeiten des VP einschließlich aller ihm in Zusammenhang mit dieser Vereinbarung entstandenen Kosten, Auslagen und Aufwendungen, wie beispielsweise Fahrt- und Reisekosten, Bürokosten, Porto und Telefongebühren, abgegolten. Dasselbe gilt für Leistungen des VP in Hinblick auf Pflege und Herstellung eines VP-Bestandes und/oder Kundenstocks, sodass im Fall der Beendigung des Vertrags unbeachtet des Grundes der Auflösung keinesfalls Ansprüche auf Abfindungen oder Ausgleiche jedweder Art gegen PROFIT PLANET bestehen.</p>
|
||||||
|
<p>7.8. Fehlerhafte Provisionszahlungen oder sonstige Zahlungen sind vom VP binnen 60 Tagen schriftlich einzumahnen. Danach gelten die Zahlungen als genehmigt.</p>
|
||||||
|
<p>7.9. Wenn vom VP keine UID-Nummer bekannt gegeben wird, erfolgen alle Auszahlungen netto.</p>
|
||||||
|
<h2>8. Vertragsstrafe, Schadenersatz</h2>
|
||||||
|
<p>8.1. Bei einem ersten Verstoß gegen die in diesem Vertrag geregelten Pflichten durch den VP erfolgt eine schriftliche Abmahnung durch PROFIT PLANET. Die Pflichtverletzung ist unmittelbar zu beenden bzw. gegebenenfalls zu beheben.</p>
|
||||||
|
<p>8.2. Kommt es erneut zu einem Verstoß gegen diesen Vertrag oder wird der zuerst gemahnte Zustand nicht beseitigt, so verpflichtet sich der VP zur Zahlung einer verschuldensunabhängigen Vertragsstrafe für jeden jeweiligen Verstoß in Höhe von EUR 5.000,00.</p>
|
||||||
|
<p>8.3. Bei Verstößen gegen die Geheimhaltungs- und Datenschutzpflichten, sowie bei besonders schwerwiegenden Verstößen, insbesondere gegen Punkt 10.2 dieses Vertrags, ist PROFIT PLANET auch ohne vorhergehende Abmahnung zur Geltendmachung der jeweiligen Vertragsstrafe berechtigt.</p>
|
||||||
|
<p>8.4. Für jede Zuwiderhandlung gegen Punkt 3.8 verpflichtet sich der VP zur Zahlung einer verschuldens- und schadensunabhängigen Konventionalstrafe an den PROFIT PLANET von EUR 5.000,00 pro Verstoß (z.B. pro an ein anderes Unternehmen oder sonstigen Dritten vermittelten Vertrags oder pro abgeworbenen Kunden). Die Geltendmachung darüber hinausgehender sonstiger Schadenersatzansprüche, der Vertragsstrafe nach 8.2 oder etwa von Erfüllungsansprüchen bleibt dadurch unberührt.</p>
|
||||||
|
<p>8.5. Für jeden Verstoß gegen die in Punkt 4. dieses Vertrags (Geheimhaltungsverpflichtung) normierten Pflichten, verpflichtet sich der VP zur Zahlung einer verschuldensunabhängigen Vertragsstrafe in Höhe von EUR 7.000,00 pro Verstoß. Die Geltendmachung weitergehender zivilrechtlicher Ansprüche – insbesondere auf Unterlassung und Schadenersatz – bleibt davon unberührt.</p>
|
||||||
|
<p>8.6. Bei Handlungen, die dem Katalog außerordentlicher Kündigungsgründe gemäß Punkt 10.2 entsprechen, insbesondere bei treuwidrigem Verhalten im Sinne der dort beschriebenen Fallgruppen (z. B. unautorisierte Kaltakquise, rufschädigendes Verhalten, unbefugtes Auftreten im Namen von PROFIT PLANET), verpflichtet sich der VP zur Zahlung einer verschuldensunabhängigen Vertragsstrafe in Höhe von EUR 10.000,00 pro Verstoß. Auch in diesen Fällen bleiben darüber hinausgehende Ansprüche – insbesondere Schadenersatz oder außerordentliche Kündigung – ausdrücklich vorbehalten.</p>
|
||||||
|
|
||||||
|
<h2>9. Haftungsausschluss</h2>
|
||||||
|
<p>9.1. Der VP führt seine Tätigkeiten nach bestem Wissen und Gewissen und in eigener Verantwortung, insbesondere auch in Bezug auf die korrekte Beratung der Endkunden aus. Eine Haftungsübernahme von PROFIT PLANET für Falschberatungen oder sonstiges Fehlverhalten des VP ist explizit ausgeschlossen.</p>
|
||||||
|
<p>9.2. Für Schäden haftet PROFIT PLANET nur, soweit diese auf Vorsatz oder grober Fahrlässigkeit oder auf grob schuldhafter Verletzung einer wesentlichen Vertragspflicht durch PROFIT PLANET, ihrer Mitarbeiter oder Erfüllungsgehilfen beruhen.</p>
|
||||||
|
<p>9.3. Eine Haftung von PROFIT PLANET für mittelbare Schäden, Folgeschäden, entgangenen Gewinn oder erwartete Ersparnis ist jedenfalls ausgeschlossen.</p>
|
||||||
|
<p>9.4. PROFIT PLANET übernimmt keine Haftung für Schäden, die durch Datenverlust auf den Servern auftreten, außer der Schaden beruht auf Vorsatz oder grober Fahrlässigkeit seitens PROFIT PLANET, ihrer Mitarbeiter oder Erfüllungsgehilfen.</p>
|
||||||
|
<p>9.5. Der Eintritt eines Schadens ist PROFIT PLANET unverzüglich mitzuteilen.</p>
|
||||||
|
<h2>10. Vertragsdauer & Kündigung</h2>
|
||||||
|
<p>10.1. Der Vertrag tritt mit Unterzeichnung oder im Fall einer Online-Registrierung, Online mit der Annahme des Vertrags durch PROFIT PLANET in Kraft und wird auf unbestimmte Zeit geschlossen. Er kann von beiden Parteien unter Einhaltung einer Frist von drei Monaten zum Ende jedes Kalendermonats schriftlich gekündigt werden.</p>
|
||||||
|
<p>10.2. Dessen ungeachtet kann der Vertrag seitens PROFIT PLANET aus wichtigem Grund ohne Einhaltung einer Kündigungsfrist gekündigt werden. Das Recht zur außerordentlichen Kündigung besteht ungeachtet weiterer Ansprüche. Folgende Gründe berechtigen insbesondere zur außerordentlichen Kündigung, die Aufzählung ist nicht abschließend:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Akte treuwidrigen Verhaltens, die eine weitere Zusammenarbeit zw. den Vertragspartnern unzumutbar machen;</li>
|
||||||
|
<li>ein solches treuwidriges Verhalten liegt insbesondere etwa dann vor, wenn ein VP ohne ausdrückliche Zustimmung eines vertretungs- und zeichnungsbefugten Organs von PROFIT PLANET Handlungen setzt, welche nach außen den Anschein erwecken, im Namen oder Auftrag von PROFIT PLANET zu erfolgen – insbesondere etwa durch Kaltakquise, Verwendung von Geschäftsdrucksorten oder -signaturen, Auftritt unter Verwendung der Marke PROFIT PLANET oder vergleichbare ruf- bzw. imageschädigende Aktivitäten.</li>
|
||||||
|
<li>die Anwendung unlauterer Praktiken oder ein grober oder wiederholter Verstoß gegen diesen Vertrag sowie der Verstoß gegen zwingende Rechtsnormen;</li>
|
||||||
|
<li>wenn über das Vermögen des jeweils anderen Vertragspartners die Einleitung eines Insolvenzverfahrens beantragt oder wenn die Eröffnung eines Insolvenzverfahrens mangels Masse abgelehnt wird;</li>
|
||||||
|
<li>Verletzung der vereinbarten oder gesetzlichen Datenschutz- oder Geheimhaltungspflichten;</li>
|
||||||
|
<li>wenn die Kooperation durch das Verhalten eines Vertragspartners oder dessen Ruf in der Öffentlichkeit den anderen Vertragspartnern einen Imageschaden zufügen würde;</li>
|
||||||
|
<li>wenn die Kooperation aufgrund der Gesetzeslage oder von dritter Seite als unzulässig untersagt wird;</li>
|
||||||
|
<li>Unzulässige Nebenabsprachen mit am Vertrieb beteiligten Dritten;</li>
|
||||||
|
</ul>
|
||||||
|
<p>10.3. Abgesehen von 10.2 kann PROFIT PLANET den VP auch außerordentlich kündigen, wenn dieser in den letzten 6 Monaten keine neuen Umsätze erzielt hat oder bei den durch seine Vermittlung zustande gekommenen Verträgen zwischen Endkunden und Produktgebern über einen Zeitraum von 2 Monaten überdurchschnittliche Stornoquoten von mehr als 30% der vermittelten Verträge bestehen. PROFIT PLANET wird den VP vor einer außerordentlichen Kündigung nach diesem Passus einmalig schriftlich verwarnen, so dass der VP die Möglichkeit hat, innerhalb einer Frist von 30 Tagen die erforderlichen neuen Umsätze zu generieren oder seine Stornoquote zu verbessern.</p>
|
||||||
|
<p>10.4. Mit der Beendigung des Vertrags steht dem VP mit Ausnahme der Provision für zu diesem Zeitpunkt bereits erfolgreich vermittelte Verträge, kein Recht auf Provision mehr zu. Ein Anspruch auf Handelsvertreterausgleich ist ausdrücklich ausgeschlossen, da der VP nicht als Handelsvertreter für den PROFIT PLANET tätig wird. Etwaige Ansprüche auf Folgeprovisionen für vermittelte Produkte bestehen für 12 Monate nach Vertragsbeendigung fort; im Falle einer außerordentlichen Kündigung verfallen Ansprüche auf Folgeprovisionen unmittelbar mit der Vertragsbeendigung.</p>
|
||||||
|
<p>10.5. Nach Beendigung des Vertrags sind vom VP sämtliche überlassenen Unterlagen und Werbematerialien unaufgefordert binnen einem Monat an PROFIT PLANET zurückzugeben. Die Verwendung der Marke PROFIT PLANET und entsprechender Logos etwa auf Briefpapier oder in E-Mail-Signaturen ist nach Beendigung des Vertrags untersagt.</p>
|
||||||
|
<h2>11. Übertragung</h2>
|
||||||
|
<p>11.1. PROFIT PLANET ist jederzeit berechtigt, den Geschäftsbetrieb ganz oder teilweise auf Dritte zu übertragen.</p>
|
||||||
|
<p>11.2. Der VP ist nur mit ausdrücklicher Zustimmung von PROFIT PLANET berechtigt, seine Vertriebsstruktur an einen Dritten zu übertragen.</p>
|
||||||
|
<p>11.3. Wenn eine als VP registrierte Kapital- oder Personengesellschaft einen neuen Gesellschafter aufnimmt, hat dies auf diesen Vertrag keine Auswirkung, sofern der/die Gesellschafter, die den VP-Antrag ursprünglich unterzeichnet haben, als Gesellschafter in der Gesellschaft verbleiben. Wenn ein Gesellschafter aus einer registrierten Gesellschaft ausscheidet oder seine Anteile an einen Dritten überträgt, so ist dies in Bezug auf diesen Vertrag zulässig, sofern er dies PROFIT PLANET schriftlich unter Vorlage der entsprechenden rechtsgültigen Urkunden anzeigt, und der Vorgang keinen anderen Bestimmungen dieses Vertrags widerspricht; anderenfalls behält PROFIT PLANET sich das Recht vor, den VP-Vertrag der betreffenden Kapital- oder Personengesellschaft aufzukündigen.</p>
|
||||||
|
<p>11.4. Bei Auflösung einer als VP registrierten Gemeinschaft (Kapital- oder Personengesellschaft, aber auch z.B. Ehepartnerschaften oder ähnliches, die einen gemeinsamen VP-Vertrag haben), bleibt nur ein VP-Vertrag bestehen. Die Mitglieder der aufzulösenden Gemeinschaft haben sich intern zu einigen, durch welches Mitglied/Gesellschafter die Vertriebspartner / Businesspartner / Affiliateschaft fortgesetzt werden soll, und dies PROFIT PLANET schriftlich anzuzeigen. Falls sich die Mitglieder der Gemeinschaft in Bezug auf die Fortsetzung des VP-vertrags nicht gütlich einigen können, behält sich PROFIT PLANET das Recht einer außerordentlichen Kündigung vor, insbesondere, wenn es durch die Uneinigkeit über die Folgen zur Vernachlässigung der Pflichten des VP, einem Verstoß gegen diesen Vertrag oder geltendes Recht oder zu einer übermäßigen Belastung der Vertriebsstruktur des VP kommt.</p>
|
||||||
|
</div>
|
||||||
|
<div class="page">
|
||||||
|
<div class="page-header"></div>
|
||||||
|
<h2>12. Schlussbestimmungen</h2>
|
||||||
|
<p>12.1. Änderungen und Ergänzungen dieser Vereinbarung bedürfen der Schriftform. Dies gilt auch für das Abgehen der Schriftformerfordernis. Mündliche Nebenabreden bestehen nicht.</p>
|
||||||
|
<p>12.2. Sollte eine Bestimmung dieser Vereinbarung unwirksam sein oder werden, gilt anstelle der unwirksamen Bestimmung jene Bestimmung als vereinbart, die dem wirtschaftlichen Zweck der unwirksamen Bestimmung am nächsten kommt.</p>
|
||||||
|
<p>12.3. Vereinbarter Gerichtsstand für alle Streitigkeiten aus oder in Zusammenhang mit dieser Vereinbarung ist das für Graz sachlich zuständige Gericht. Diese Vereinbarung unterliegt österreichischem Recht, nicht jedoch den nichtzwingenden Verweisungsnormen des IPR. Weiter- bzw. Rückverweisungen sind ausgeschlossen. Darüber hinaus steht es PROFIT PLANET frei, den VP auch seinem allgemeinen Gerichtsstand zu klagen.</p>
|
||||||
|
<div class="signatures">
|
||||||
|
<div class="signature" style="flex:1;text-align:center;">
|
||||||
|
<p style="margin:0 0 6px;">Für PROFIT PLANET (Auftraggeber)</p>
|
||||||
|
<!-- CHANGED: wrap stamp + date in a flex column with spacing to avoid overlap -->
|
||||||
|
<div class="sig-block" style="display:flex;flex-direction:column;align-items:center;gap:6px;min-height:140px;">
|
||||||
|
<div class="pp-stamp" style="display:block;max-width:220px;margin:0 auto 6px;">{{profitplanetSignature}}</div>
|
||||||
|
<div class="sig-date" style="font-size:0.75em;line-height:1.2;">{{currentDate}}</div>
|
||||||
|
</div>
|
||||||
|
<p style="margin:0 0 6px;">Datum, Unterschrift</p>
|
||||||
|
</div>
|
||||||
|
<div class="signature">
|
||||||
|
<p style="margin:0 0 6px;">Für den VP (Auftragnehmer)</p>
|
||||||
|
<div class="sig-block">
|
||||||
|
<span class="sig-image">{{signatureImage}}</span>
|
||||||
|
<div style="font-size:0.75em;line-height:1.2;">{{fullName}}</div>
|
||||||
|
<div style="font-size:0.75em;line-height:1.2;">{{currentDate}}</div>
|
||||||
|
</div>
|
||||||
|
<p style="margin:0 0 6px;">Name, Datum, Unterschrift</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
209
debug-pdf/template_1_html_raw.bin
Normal file
209
debug-pdf/template_1_html_raw.bin
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>VERTRIEBSPARTNER / BUSINESSPARTNER / AFFILIATE - VERTRAG</title>
|
||||||
|
<style>
|
||||||
|
/* PDF friendly page setup */
|
||||||
|
@page { size:A4; margin:15mm 12mm 18mm 12mm; }
|
||||||
|
body { font-family:Arial,Helvetica,sans-serif; line-height:1.4; font-size:13px; counter-reset: page; margin:0; }
|
||||||
|
h1 { text-align:center; font-size:18px; margin:0 0 8px; }
|
||||||
|
h2 { margin:16px 0 6px; font-size:13px; }
|
||||||
|
.page { page-break-after:always; padding:12px 20px 18px; }
|
||||||
|
.page:last-child { page-break-after:auto; }
|
||||||
|
.page-header { display:flex; justify-content:flex-end; font-size:0.65em; counter-increment:page; }
|
||||||
|
.page-header:after { content:"Seite " counter(page); }
|
||||||
|
.meta-info { border:1px solid #000; padding:8px 12px; margin:12px 0 25px; font-size:0.9em; }
|
||||||
|
.meta-info table { width:100%; border-collapse:collapse; }
|
||||||
|
.meta-info td { padding:3px 6px; vertical-align:top; border-bottom:1px solid #ccc; }
|
||||||
|
.meta-info td:first-child { font-weight:bold; width:28%; white-space:nowrap; }
|
||||||
|
.meta-info tr:last-child td { border-bottom:0; }
|
||||||
|
/* Unified signatures */
|
||||||
|
.signatures { display:flex; gap:30px; margin-top:38px; }
|
||||||
|
.signature { flex:1; text-align:center; }
|
||||||
|
/* Added: extra space below company stamp so date sits clearly underneath */
|
||||||
|
.signature-company .sig-image { margin-bottom:22px !important; }
|
||||||
|
.signature-company .sig-date { margin-top:0 !important; }
|
||||||
|
.sig-block { display:flex; flex-direction:column; align-items:center; gap:6px; min-height:120px; }
|
||||||
|
.sig-image { display:block; max-width:180px !important; max-height:70px !important; height:auto !important; margin:0 auto 6px; }
|
||||||
|
.sig-date { margin-top:4px; display:block; }
|
||||||
|
.page-header-block{display:flex;flex-direction:column;align-items:flex-end;gap:3px;margin-bottom:6px;}
|
||||||
|
.print-date{font-size:0.7em;}
|
||||||
|
@media print {
|
||||||
|
body { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
|
||||||
|
}
|
||||||
|
/* ADDED: full size Profit Planet signature */
|
||||||
|
.pp-stamp,
|
||||||
|
.pp-stamp img {
|
||||||
|
max-width:none !important;
|
||||||
|
max-height:none !important;
|
||||||
|
width:auto !important;
|
||||||
|
height:auto !important;
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<div class="page-header-block">
|
||||||
|
<div class="page-header"></div>
|
||||||
|
<div class="print-date">Erstellt am: {{currentDate}}</div>
|
||||||
|
</div>
|
||||||
|
<h1>VERTRIEBSPARTNER / BUSINESSPARTNER / AFFILIATE - VERTRAG</h1>
|
||||||
|
<p style="text-align:center;margin:0 0 6px;">idF 21.05.2025</p>
|
||||||
|
<p>abgeschlossen zwischen</p>
|
||||||
|
<p>Profit Planet GmbH (kurz PROFIT PLANET)<br>FN 649474i<br>Liebenauer Hauptstraße 82c<br>A-8041 Graz</p>
|
||||||
|
<p>und</p>
|
||||||
|
<p>Vertriebspartner / Businesspartner / Affiliate (kurz VP)</p>
|
||||||
|
<div class="meta-info">
|
||||||
|
<table class="meta-grid">
|
||||||
|
<tr>
|
||||||
|
<td>Vertriebspartner</td>
|
||||||
|
<td>{{fullName}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Adresse</td>
|
||||||
|
<td>{{address}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>PLZ / Ort</td>
|
||||||
|
<td>{{zip_code}} {{city}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Vollständige Adresse</td>
|
||||||
|
<td>{{fullAddress}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>E-Mail / Telefon</td>
|
||||||
|
<td>{{email}} / {{phone}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<h2>1. Präambel und Vertragsgegenstand</h2>
|
||||||
|
<p>1.1. Dieser Vertrag regelt die Zusammenarbeit zwischen PROFIT PLANET und VP als Grundlage einer fairen, langfristigen und erfolgreichen Kooperation. Die VP unterstützen einander im Sinne der Ziele der Zusammenarbeit und unterrichten sich gegenseitig über alle Vorgänge, die für ihre Leistungen im Rahmen der Kooperation von Interesse sind.</p>
|
||||||
|
<p>1.2. PROFIT PLANET bietet über ein Vertriebspartner / Businesspartner / Affiliate-Netzwerk den Vertrieb verschiedener Dienstleistungen und Produkte, vornehmlich aus den Bereichen Nachhaltigkeit, Energie, Handel sowie Consulting und Coaching an.</p>
|
||||||
|
<p>1.3. Der VP vermittelt die jeweiligen Dienstleistungen, Produkte oder qualifizierten Leads, die zu einem Abschluss führen, und erhält dafür eine Provision. Für die Tätigkeit als VP ist es nicht erforderlich, weitere VP zu werben.</p>
|
||||||
|
<p>1.4. Der VP ist berechtigt, weitere Vertriebspartner / Businesspartner / Affiliate für den Vertrieb der Dienstleistungen und Produkte zu gewinnen. Für die Vermittlung und Betreuung der von ihm akquirierten Vertriebspartner / Businesspartner / Affiliate erhält der werbende VP eine Provision, die sich aus den erwirtschafteten Umsätzen der geworbenen VP ermittelt. Die Höhe der Provision ergibt sich aus der Provisionsübersicht.</p>
|
||||||
|
<p>1.5. Die Vertragsabschlüsse kommen nur zwischen dem Endkunden und dem jeweiligen Dienstleister und/oder Produktgeber (Energieversorgungs-, Handels-, Dienstleistungs- oder Coachingunternehmen) zustande, ohne dass dadurch eine Vertragsbeziehung zwischen dem VP und dem Endkunden entsteht. Ein Anspruch auf Abschluss des jeweiligen Vertrags seitens des Endkunden gegenüber PROFIT PLANET oder dem VP entsteht nicht; der Vertragsabschluss ist von der Annahme des entsprechenden Antrags durch den Dienstleister bzw. Produktgeber abhängig. PROFIT PLANET hat darauf keinen Einfluss.</p>
|
||||||
|
<p>1.6. PROFIT PLANET behält sich vor, die angebotenen Produkte zurückzuziehen, zu ändern, neue hinzuzufügen oder sonstige Anpassungen des Produktangebots vorzunehmen. PROFIT PLANET wird den VP über Änderungen von Produkten oder Tarifen nach Maßgabe der Möglichkeiten rechtzeitig vor Wirksamkeit der Änderungen informieren.</p>
|
||||||
|
<p>1.7. Die genauen Produktbestandteile und Konditionen ergeben sich aus dem jeweiligen Produktpartnerinformationsblatt, welches auf der Online-Plattform hinterlegt wird.</p>
|
||||||
|
<p>1.8. PROFIT PLANET ist berechtigt, nach eigenem Ermessen andere Personen und Unternehmen mit der Vermittlung von Produkten und Dienstleistungen von PROFIT PLANET bzw. Produktpartnern von PROFIT PLANET zu beauftragen. Es bestehen grundsätzlich keine Alleinvermittlungsaufträge und keine Exklusivität.</p>
|
||||||
|
|
||||||
|
<h2>2. Vertriebspartner / Businesspartner / Affiliate werden</h2>
|
||||||
|
<p>2.1. Kapitalgesellschaften, Personengesellschaften und volljährige natürliche Personen können Vertriebspartner / Businesspartner / Affiliate des PROFIT PLANET werden; pro Entität ist die Registrierung nur eines VP-Vertrags vorgesehen. Natürliche Personen, die bloß als Verbraucher handeln (wollen), können nicht Vertriebspartner / Businesspartner / Affiliate von PROFIT PLANET werden.</p>
|
||||||
|
<p>2.2. Kapitalgesellschaften müssen ihrem VP-Antrag die Firmenbuchnummer und gegebenenfalls die Umsatzsteuer-Identifikationsnummer (UID) beilegen. Der Antrag muss von allen Zeichnungsbereichten der Gesellschaft derart gezeichnet werden, dass eine rechtwirksame Vertretung sichergestellt ist. Die Gesellschafter haften gegenüber PROFIT PLANET jeweils persönlich für das Verhalten der Gesellschaft.</p>
|
||||||
|
<p>2.3. Absatz 2.2 gilt inhaltsgemäß auch für Personengesellschaften.</p>
|
||||||
|
<p>2.4. Der VP ist verpflichtet, Änderungen seiner unternehmens- oder personenbezogenen Daten unverzüglich an PROFIT PLANET zu melden.</p>
|
||||||
|
<p>2.5. Für die Verwendung des Online-Systems gelten die allgemeinen Geschäftsbedingungen.</p>
|
||||||
|
<p>2.6. PROFIT PLANET kann Vertriebspartner / Businesspartner / Affiliate ohne Angabe von Gründen ablehnen.</p>
|
||||||
|
|
||||||
|
<h2>3. Leistungen / Pflichten des VP</h2>
|
||||||
|
<p>3.1. Der VP handelt unabhängig als selbständiger Unternehmer, er ist weder Arbeitnehmer noch Handelsvertreter oder Makler von PROFIT PLANET. Er ist bei der Vermittlung von Produktverträgen eigenverantwortlich tätig, handelt abgesehen von den Pflichten aus diesem Vertrag frei von Weisungen und ist nicht mit der ständigen Vermittlung von Geschäften betraut. Es bestehen seitens PROFIT PLANET keine Umsatzvorgaben und keine Abnahme- oder Vertriebspflichten. Der VP trägt alle mit der Kundenakquisition verbundenen Kosten und Risiken selbst und verwendet eigene Betriebsmittel. Er stellt im geschäftlichen Verkehr klar, dass er nicht im Auftrag oder im Namen von PROFIT PLANET handelt, sondern als unabhängiger Vertriebspartner / Businesspartner / Affiliate.</p>
|
||||||
|
<p>3.2. Der VP betreibt sein Unternehmen mit der Sorgfalt eines ordentlichen Kaufmanns und ist für die Einhaltung aller gesetzlichen sowie der steuer- und sozialrechtlichen Vorgaben selbst verantwortlich.</p>
|
||||||
|
<p>3.3. Der VP hält sich insbesondere auch an das Wettbewerbsrecht und nimmt Abstand von ungenehmigter, irreführender oder sonst unlauterer Werbung. Der VP verpflichtet sich auch, falsche oder irreführende Aussagen über Dienstleistungen, Produkte und Vertriebssystem der PROFIT PLANET zu unterlassen.</p>
|
||||||
|
<p>3.4. Grundsätzlich steht es dem VP frei, Produkte / Dienstleistungen auch für andere Unternehmen zu vertreiben. Falls es allerdings in der Zusammenarbeit mit einem anderen Dienstleister oder Produktgeber in räumlicher oder zeitlicher Nähe zu Überschneidungen im Vertrieb, insbesondere bei Terminisierungen, Promotion-Auftritten (POS) oder anderen dienstleistungs- oder produktspezifischen Werbetätigkeiten kommen, so wäre dies nur nach ausdrücklicher Zustimmung durch PROFIT PLANET zulässig.</p>
|
||||||
|
<p>3.5. Beim Abschluss von Kundenverträgen ist der VP verpflichtet, die von PROFIT PLANET zur Verfügung gestellten Originalunterlagen (zB Antragsformulare, AGB, sonstige Unterlagen der Dienstleister oder Produktgeber) in der jeweils aktuellen Version zu verwenden und dem Kunden bei Vertragsabschluss vorzulegen bzw. auszuhändigen. Die Originalunterlagen sind durch den VP nicht zu verändern, missbräuchliche Verwendung ist zu verhindern.</p>
|
||||||
|
<p>3.6. Kundenverträge in Papierform sind vom VP unverzüglich, spätestens jedoch binnen 1 Woche nach Aufforderung durch PROFIT PLANET oder den Produktgeber an PROFIT PLANET auszuhändigen.</p>
|
||||||
|
<p>3.7. Sämtliche Präsentations-, Werbe- und Schulungsmaterialien sowie label von PROFIT PLANET sind urheberrechtlich geschützt und dürfen ohne ausdrückliches Einverständnis von PROFIT PLANET weder ganz noch teilweise vervielfältigt, verbreitet oder öffentlich zugänglich gemacht werden. Die Herstellung, Verwendung und Verbreitung eigener Werbemittel, Schulungsmaterialien oder Produktbroschüren ist nur nach schriftlicher Genehmigung und Freigabe durch PROFIT PLANET gestattet.</p>
|
||||||
|
<p>3.8. Der VP ist während der Dauer dieser Vereinbarung und für die Dauer von 36 Monaten nach Beendigung dieses Vertrags aus welchem Grund immer, nicht berechtigt, unmittelbar selbst bzw. mittelbar über Dritte Kunden von PROFIT PLANET und ihrer Produktpartner, einschließlich der vom VP vermittelten Endkunden, durch direkte Ansprache abzuwerben. Als Abwerben gilt jede Form des direkten Herantretens an den Kunden mit der Absicht, ihn zum Wechsel zu einem anderen Energieversorgungs-, Dienstleistungs-, Handels-, und/oder Coachingunternehmen zu bewegen (beispielsweise etwa durch Anrufe beim Kunden, Direktmailing mit Absicht der Abwerbung, Haustürgeschäfte etc.).</p>
|
||||||
|
<h2>4. Geheimhaltung</h2>
|
||||||
|
<p>4.1. Der VP verpflichtet sich, Geschäfts- und Betriebsgeheimnisse und sonstige vertrauliche Informationen von PROFIT PLANET und dessen Struktur, Geschäftspartner, Vertriebspartner / Businesspartner / Affiliate, Produktgeber, Provisionen und Endkunden unter äußerster Geheimhaltung zu behandeln und zu verwahren und diese Daten nur nach erfolgter schriftlicher Zustimmung durch den PROFIT PLANET an Dritte weiterzugeben.</p>
|
||||||
|
<p>4.2. Diese Verpflichtung gilt auch für Mitarbeiter und Unter-Vertriebspartner / Businesspartner / Affiliate des VP. Der VP hat für das Verhalten allfälliger Erfüllungsgehilfen und/oder Subpartner einzustehen.</p>
|
||||||
|
<p>4.3. Zu den Geschäftsgeheimnissen gehören insbesondere auch Informationen zu internen Betriebsabläufen, Provisionen und Provisionsstrukturen, Produkt- und Preiskalkulationen, Vertriebspartner / Businesspartner / Affiliate-strukturen und -aktivitäten.</p>
|
||||||
|
<p>4.4. Dem VP ist es nicht gestattet, auf Presseanfragen zu PROFIT PLANET, dessen Provisionspläne, Produkte oder andere Leistungen zu antworten. Presseanfragen sind immer an PROFIT PLANET weiterzuleiten.</p>
|
||||||
|
<h2>5. Datenschutz</h2>
|
||||||
|
<p>5.1. Die Vertragspartner sind verpflichtet, die gesetzlichen Datenschutzbestimmungen vollumfänglich einzuhalten. Für Verstöße gegen datenschutzrechtliche Schutzbestimmungen haftet ausschließlich der jeweils die Bestimmung verletzende Vertragspartner, dieser wird den schuldlos handelnden Vertragspartner von allen entsprechenden Ansprüchen freistellen und schad- und klaglos halten.</p>
|
||||||
|
<p>5.2. Im Regelfall ist der VP ist hinsichtlich der Daten der von ihm vermittelten Endkunden und Akquisitionskontakte Subauftragsverarbeiter im Sinne der Datenschutzgesetze (DSG, DSGVO); PROFIT PLANET ist Auftragsverarbeiter im Sinne der DSGVO. Soweit durch die gesetzlichen Bestimmungen vorgesehen, werden zu dieser Vereinbarung entsprechende datenschutzrechtliche Zusatzverträge abgeschlossen.</p>
|
||||||
|
<p>5.3. PROFIT PLANET ist bezüglich der Daten des VP auf Datenschutz verpflichtet. Die Datenschutzerklärung ist Online jederzeit abrufbar.</p>
|
||||||
|
<h2>6. VP-Schutz</h2>
|
||||||
|
<p>6.1. Ein neu geworbener VP wird in die Struktur desjenigen VP zugewiesen, der ihn geworben hat (VP-Schutz). Wenn mehrere VP denselben VP neu melden, wird seitens PROFIT PLANET nur die zuerst erfolgte Meldung berücksichtigt, wobei das Eingangsdatum des Registrierungsantrags bei PROFIT PLANET für die Zuteilung maßgeblich ist.</p>
|
||||||
|
<p>6.2. Der meldende VP ist verantwortlich dafür, die Daten des geworbenen VP vollständig und ordentlich zu übermitteln. PROFIT PLANET ist berechtigt, die Daten eines geworbenen VP aus ihrem System zu löschen, wenn von diesem innerhalb einer angemessenen Frist keine Umsätze oder Rückmeldungen kommen.</p>
|
||||||
|
<p>6.3. Ein Wechsel von der Struktur eines VP in die eines anderen ist grundsätzlich ausgeschlossen und nur ausnahmsweise möglich, wenn der wechselwillige VP nachweist, dass der in der Struktur über ihm stehende VP versucht hat, ihn zu einem gesetzes- oder vertragswidrigen Verhalten zu veranlassen oder sonst schwerwiegende Vorfälle die weitere Zusammenarbeit in der Struktur dieses VP untragbar machen. Über einen entsprechenden schriftlichen Antrag entscheidet PROFIT PLANET nach freiem Ermessen.</p>
|
||||||
|
<p>6.4. Ein VP, der innerhalb der letzten 12 Monate bereits einen VP-Vertrag mit PROFIT PLANET hatte, kann nicht geworben werden.</p>
|
||||||
|
<p>6.5. Eine Umgehung des VP-Schutzes etwa durch Verwendung der Namen von Strohnamen, -personen oder -firmen ist untersagt.</p>
|
||||||
|
<p>6.6. PROFIT PLANET räumt ihren VP ausdrücklich keinen Gebietsschutz ein. Alle VP können europaweit ohne Einschränkungen tätig sein.</p>
|
||||||
|
<h2>7. Provision</h2>
|
||||||
|
<p>7.1. Für jedes vom VP erfolgreich vermittelte Vertragsverhältnis zwischen Produktgeber und Endkunden erwirbt der VP Anspruch auf Provision als Bearbeitungs- und Aufwandspauschale</p>
|
||||||
|
<p>7.2. Die Höhe der Provision richtet sich nach der jeweils aktuell gültigen Provisionsübersicht laut Marketingkonzept. Die jeweils gültige Fassung dieser Provisionsübersicht ist jederzeit auf der Website von PROFIT PLANET (www.profit-planet.com) im internen Bereich abrufbar, einsehbar, downloadbar und kann dort auch auf Anfrage zur Verfügung gestellt werden. Änderungen der Provisionsübersicht werden dem VP rechtzeitig bekannt gegeben. Es gelten jeweils die zum Zeitpunkt der Vermittlung gültigen Provisionssätze.</p>
|
||||||
|
<p>7.3. Als erfolgreiche Vermittlung im Sinne dieses Vertrages gilt, wenn das Vertragsverhältnis zwischen Endkunden und Produktpartner tatsächlich zustande gekommen ist. Insbesondere entsteht kein Provisionsanspruch, wenn</p>
|
||||||
|
<ul>
|
||||||
|
<li>der Kunde von seinen Widerrufs- oder Rücktrittsrechten Gebrauch macht,</li>
|
||||||
|
<li>der Vertrag rechtswirksam angefochten wird,</li>
|
||||||
|
<li>der Kunde vom Dienstleister oder Produktpartner aus welchem Grund auch immer nicht angenommen wird,</li>
|
||||||
|
<li>fehlerhafte oder unvollständige Kundenanträge eingereicht werden,</li>
|
||||||
|
<li>der Vertrag widerrechtlich zustande gekommen ist oder</li>
|
||||||
|
<li>der Dienstleister oder Produktgeber die Auszahlung der Provision an PROFIT PLANET aus Gründen, die nicht von PROFIT PLANET zu verantworten sind, verweigert.</li>
|
||||||
|
</ul>
|
||||||
|
<p>7.4. Anspruch auf Auszahlung der Provision entsteht gegenüber PROFIT PLANET grundsätzlich erst dann, wenn die Zahlungen seitens des Geschäftspartners / Produktgebers bei PROFIT PLANET eingelangt sind und alle sonstigen Auszahlungsvoraussetzungen vorliegen. Der VP nimmt zur Kenntnis, dass die exakten Zahlungsmodalitäten bei den verschiedenen Dienstleistern oder Produktgebern voneinander abweichen können und PROFIT PLANET diese Unterschiede bei der Auszahlung berücksichtigt. Die unterschiedlichen Zeitspannen divergieren je nach Partnerunternehmen derzeit durchschnittlich zwischen 30 bis 100 Tage. Die genauen Anforderungen und Konditionen ergeben sich aus dem jeweiligen Produktpartnerinformationsblatt und dem Marketingkonzept.</p>
|
||||||
|
<p>7.5. Die Auszahlung durch PROFIT PLANET erfolgt einmal monatlich, ungefähr um den 20. des auf den Zahlungseingang bei PROFIT PLANET folgenden Monats. Die Auszahlung erfolgt bargeldlos per Überweisung auf das vom VP genannte Konto. PROFIT PLANET kann Zahlungen bis zu einer Höhe von EUR 100,00 von der Auszahlung ausschließen (Mindestauszahlungshöhe); die nicht ausbezahlten Provisionsansprüche werden auf dem Provisionskonto des VP rechnerisch fortgeführt und im Folgemonat nach Erreichen der Mindestauszahlungshöhe ausbezahlt. Beträge unterhalb der Mindestauszahlungshöhe werden einmal jährlich zur Auszahlung gebracht.</p>
|
||||||
|
<p>7.6. Der Provisionsanspruch entfällt rückwirkend, wenn PROFIT PLANET, Provisionen an einen Produktgeber zurückzahlen muss, etwa weil ein Kunde den Vertrag widerruft oder andere Ausschlusskriterien seitens des Produktgebers vorliegen (Stornohaftung etc.). PROFIT PLANET ist berechtigt, Forderungen, die dem PROFIT PLANET gegen den VP zustehen, mit dessen Provisionsansprüchen ganz oder teilweise aufzurechnen.</p>
|
||||||
|
<p>7.7. Mit dieser Provision sind sämtliche Tätigkeiten des VP einschließlich aller ihm in Zusammenhang mit dieser Vereinbarung entstandenen Kosten, Auslagen und Aufwendungen, wie beispielsweise Fahrt- und Reisekosten, Bürokosten, Porto und Telefongebühren, abgegolten. Dasselbe gilt für Leistungen des VP in Hinblick auf Pflege und Herstellung eines VP-Bestandes und/oder Kundenstocks, sodass im Fall der Beendigung des Vertrags unbeachtet des Grundes der Auflösung keinesfalls Ansprüche auf Abfindungen oder Ausgleiche jedweder Art gegen PROFIT PLANET bestehen.</p>
|
||||||
|
<p>7.8. Fehlerhafte Provisionszahlungen oder sonstige Zahlungen sind vom VP binnen 60 Tagen schriftlich einzumahnen. Danach gelten die Zahlungen als genehmigt.</p>
|
||||||
|
<p>7.9. Wenn vom VP keine UID-Nummer bekannt gegeben wird, erfolgen alle Auszahlungen netto.</p>
|
||||||
|
<h2>8. Vertragsstrafe, Schadenersatz</h2>
|
||||||
|
<p>8.1. Bei einem ersten Verstoß gegen die in diesem Vertrag geregelten Pflichten durch den VP erfolgt eine schriftliche Abmahnung durch PROFIT PLANET. Die Pflichtverletzung ist unmittelbar zu beenden bzw. gegebenenfalls zu beheben.</p>
|
||||||
|
<p>8.2. Kommt es erneut zu einem Verstoß gegen diesen Vertrag oder wird der zuerst gemahnte Zustand nicht beseitigt, so verpflichtet sich der VP zur Zahlung einer verschuldensunabhängigen Vertragsstrafe für jeden jeweiligen Verstoß in Höhe von EUR 5.000,00.</p>
|
||||||
|
<p>8.3. Bei Verstößen gegen die Geheimhaltungs- und Datenschutzpflichten, sowie bei besonders schwerwiegenden Verstößen, insbesondere gegen Punkt 10.2 dieses Vertrags, ist PROFIT PLANET auch ohne vorhergehende Abmahnung zur Geltendmachung der jeweiligen Vertragsstrafe berechtigt.</p>
|
||||||
|
<p>8.4. Für jede Zuwiderhandlung gegen Punkt 3.8 verpflichtet sich der VP zur Zahlung einer verschuldens- und schadensunabhängigen Konventionalstrafe an den PROFIT PLANET von EUR 5.000,00 pro Verstoß (z.B. pro an ein anderes Unternehmen oder sonstigen Dritten vermittelten Vertrags oder pro abgeworbenen Kunden). Die Geltendmachung darüber hinausgehender sonstiger Schadenersatzansprüche, der Vertragsstrafe nach 8.2 oder etwa von Erfüllungsansprüchen bleibt dadurch unberührt.</p>
|
||||||
|
<p>8.5. Für jeden Verstoß gegen die in Punkt 4. dieses Vertrags (Geheimhaltungsverpflichtung) normierten Pflichten, verpflichtet sich der VP zur Zahlung einer verschuldensunabhängigen Vertragsstrafe in Höhe von EUR 7.000,00 pro Verstoß. Die Geltendmachung weitergehender zivilrechtlicher Ansprüche – insbesondere auf Unterlassung und Schadenersatz – bleibt davon unberührt.</p>
|
||||||
|
<p>8.6. Bei Handlungen, die dem Katalog außerordentlicher Kündigungsgründe gemäß Punkt 10.2 entsprechen, insbesondere bei treuwidrigem Verhalten im Sinne der dort beschriebenen Fallgruppen (z. B. unautorisierte Kaltakquise, rufschädigendes Verhalten, unbefugtes Auftreten im Namen von PROFIT PLANET), verpflichtet sich der VP zur Zahlung einer verschuldensunabhängigen Vertragsstrafe in Höhe von EUR 10.000,00 pro Verstoß. Auch in diesen Fällen bleiben darüber hinausgehende Ansprüche – insbesondere Schadenersatz oder außerordentliche Kündigung – ausdrücklich vorbehalten.</p>
|
||||||
|
|
||||||
|
<h2>9. Haftungsausschluss</h2>
|
||||||
|
<p>9.1. Der VP führt seine Tätigkeiten nach bestem Wissen und Gewissen und in eigener Verantwortung, insbesondere auch in Bezug auf die korrekte Beratung der Endkunden aus. Eine Haftungsübernahme von PROFIT PLANET für Falschberatungen oder sonstiges Fehlverhalten des VP ist explizit ausgeschlossen.</p>
|
||||||
|
<p>9.2. Für Schäden haftet PROFIT PLANET nur, soweit diese auf Vorsatz oder grober Fahrlässigkeit oder auf grob schuldhafter Verletzung einer wesentlichen Vertragspflicht durch PROFIT PLANET, ihrer Mitarbeiter oder Erfüllungsgehilfen beruhen.</p>
|
||||||
|
<p>9.3. Eine Haftung von PROFIT PLANET für mittelbare Schäden, Folgeschäden, entgangenen Gewinn oder erwartete Ersparnis ist jedenfalls ausgeschlossen.</p>
|
||||||
|
<p>9.4. PROFIT PLANET übernimmt keine Haftung für Schäden, die durch Datenverlust auf den Servern auftreten, außer der Schaden beruht auf Vorsatz oder grober Fahrlässigkeit seitens PROFIT PLANET, ihrer Mitarbeiter oder Erfüllungsgehilfen.</p>
|
||||||
|
<p>9.5. Der Eintritt eines Schadens ist PROFIT PLANET unverzüglich mitzuteilen.</p>
|
||||||
|
<h2>10. Vertragsdauer & Kündigung</h2>
|
||||||
|
<p>10.1. Der Vertrag tritt mit Unterzeichnung oder im Fall einer Online-Registrierung, Online mit der Annahme des Vertrags durch PROFIT PLANET in Kraft und wird auf unbestimmte Zeit geschlossen. Er kann von beiden Parteien unter Einhaltung einer Frist von drei Monaten zum Ende jedes Kalendermonats schriftlich gekündigt werden.</p>
|
||||||
|
<p>10.2. Dessen ungeachtet kann der Vertrag seitens PROFIT PLANET aus wichtigem Grund ohne Einhaltung einer Kündigungsfrist gekündigt werden. Das Recht zur außerordentlichen Kündigung besteht ungeachtet weiterer Ansprüche. Folgende Gründe berechtigen insbesondere zur außerordentlichen Kündigung, die Aufzählung ist nicht abschließend:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Akte treuwidrigen Verhaltens, die eine weitere Zusammenarbeit zw. den Vertragspartnern unzumutbar machen;</li>
|
||||||
|
<li>ein solches treuwidriges Verhalten liegt insbesondere etwa dann vor, wenn ein VP ohne ausdrückliche Zustimmung eines vertretungs- und zeichnungsbefugten Organs von PROFIT PLANET Handlungen setzt, welche nach außen den Anschein erwecken, im Namen oder Auftrag von PROFIT PLANET zu erfolgen – insbesondere etwa durch Kaltakquise, Verwendung von Geschäftsdrucksorten oder -signaturen, Auftritt unter Verwendung der Marke PROFIT PLANET oder vergleichbare ruf- bzw. imageschädigende Aktivitäten.</li>
|
||||||
|
<li>die Anwendung unlauterer Praktiken oder ein grober oder wiederholter Verstoß gegen diesen Vertrag sowie der Verstoß gegen zwingende Rechtsnormen;</li>
|
||||||
|
<li>wenn über das Vermögen des jeweils anderen Vertragspartners die Einleitung eines Insolvenzverfahrens beantragt oder wenn die Eröffnung eines Insolvenzverfahrens mangels Masse abgelehnt wird;</li>
|
||||||
|
<li>Verletzung der vereinbarten oder gesetzlichen Datenschutz- oder Geheimhaltungspflichten;</li>
|
||||||
|
<li>wenn die Kooperation durch das Verhalten eines Vertragspartners oder dessen Ruf in der Öffentlichkeit den anderen Vertragspartnern einen Imageschaden zufügen würde;</li>
|
||||||
|
<li>wenn die Kooperation aufgrund der Gesetzeslage oder von dritter Seite als unzulässig untersagt wird;</li>
|
||||||
|
<li>Unzulässige Nebenabsprachen mit am Vertrieb beteiligten Dritten;</li>
|
||||||
|
</ul>
|
||||||
|
<p>10.3. Abgesehen von 10.2 kann PROFIT PLANET den VP auch außerordentlich kündigen, wenn dieser in den letzten 6 Monaten keine neuen Umsätze erzielt hat oder bei den durch seine Vermittlung zustande gekommenen Verträgen zwischen Endkunden und Produktgebern über einen Zeitraum von 2 Monaten überdurchschnittliche Stornoquoten von mehr als 30% der vermittelten Verträge bestehen. PROFIT PLANET wird den VP vor einer außerordentlichen Kündigung nach diesem Passus einmalig schriftlich verwarnen, so dass der VP die Möglichkeit hat, innerhalb einer Frist von 30 Tagen die erforderlichen neuen Umsätze zu generieren oder seine Stornoquote zu verbessern.</p>
|
||||||
|
<p>10.4. Mit der Beendigung des Vertrags steht dem VP mit Ausnahme der Provision für zu diesem Zeitpunkt bereits erfolgreich vermittelte Verträge, kein Recht auf Provision mehr zu. Ein Anspruch auf Handelsvertreterausgleich ist ausdrücklich ausgeschlossen, da der VP nicht als Handelsvertreter für den PROFIT PLANET tätig wird. Etwaige Ansprüche auf Folgeprovisionen für vermittelte Produkte bestehen für 12 Monate nach Vertragsbeendigung fort; im Falle einer außerordentlichen Kündigung verfallen Ansprüche auf Folgeprovisionen unmittelbar mit der Vertragsbeendigung.</p>
|
||||||
|
<p>10.5. Nach Beendigung des Vertrags sind vom VP sämtliche überlassenen Unterlagen und Werbematerialien unaufgefordert binnen einem Monat an PROFIT PLANET zurückzugeben. Die Verwendung der Marke PROFIT PLANET und entsprechender Logos etwa auf Briefpapier oder in E-Mail-Signaturen ist nach Beendigung des Vertrags untersagt.</p>
|
||||||
|
<h2>11. Übertragung</h2>
|
||||||
|
<p>11.1. PROFIT PLANET ist jederzeit berechtigt, den Geschäftsbetrieb ganz oder teilweise auf Dritte zu übertragen.</p>
|
||||||
|
<p>11.2. Der VP ist nur mit ausdrücklicher Zustimmung von PROFIT PLANET berechtigt, seine Vertriebsstruktur an einen Dritten zu übertragen.</p>
|
||||||
|
<p>11.3. Wenn eine als VP registrierte Kapital- oder Personengesellschaft einen neuen Gesellschafter aufnimmt, hat dies auf diesen Vertrag keine Auswirkung, sofern der/die Gesellschafter, die den VP-Antrag ursprünglich unterzeichnet haben, als Gesellschafter in der Gesellschaft verbleiben. Wenn ein Gesellschafter aus einer registrierten Gesellschaft ausscheidet oder seine Anteile an einen Dritten überträgt, so ist dies in Bezug auf diesen Vertrag zulässig, sofern er dies PROFIT PLANET schriftlich unter Vorlage der entsprechenden rechtsgültigen Urkunden anzeigt, und der Vorgang keinen anderen Bestimmungen dieses Vertrags widerspricht; anderenfalls behält PROFIT PLANET sich das Recht vor, den VP-Vertrag der betreffenden Kapital- oder Personengesellschaft aufzukündigen.</p>
|
||||||
|
<p>11.4. Bei Auflösung einer als VP registrierten Gemeinschaft (Kapital- oder Personengesellschaft, aber auch z.B. Ehepartnerschaften oder ähnliches, die einen gemeinsamen VP-Vertrag haben), bleibt nur ein VP-Vertrag bestehen. Die Mitglieder der aufzulösenden Gemeinschaft haben sich intern zu einigen, durch welches Mitglied/Gesellschafter die Vertriebspartner / Businesspartner / Affiliateschaft fortgesetzt werden soll, und dies PROFIT PLANET schriftlich anzuzeigen. Falls sich die Mitglieder der Gemeinschaft in Bezug auf die Fortsetzung des VP-vertrags nicht gütlich einigen können, behält sich PROFIT PLANET das Recht einer außerordentlichen Kündigung vor, insbesondere, wenn es durch die Uneinigkeit über die Folgen zur Vernachlässigung der Pflichten des VP, einem Verstoß gegen diesen Vertrag oder geltendes Recht oder zu einer übermäßigen Belastung der Vertriebsstruktur des VP kommt.</p>
|
||||||
|
</div>
|
||||||
|
<div class="page">
|
||||||
|
<div class="page-header"></div>
|
||||||
|
<h2>12. Schlussbestimmungen</h2>
|
||||||
|
<p>12.1. Änderungen und Ergänzungen dieser Vereinbarung bedürfen der Schriftform. Dies gilt auch für das Abgehen der Schriftformerfordernis. Mündliche Nebenabreden bestehen nicht.</p>
|
||||||
|
<p>12.2. Sollte eine Bestimmung dieser Vereinbarung unwirksam sein oder werden, gilt anstelle der unwirksamen Bestimmung jene Bestimmung als vereinbart, die dem wirtschaftlichen Zweck der unwirksamen Bestimmung am nächsten kommt.</p>
|
||||||
|
<p>12.3. Vereinbarter Gerichtsstand für alle Streitigkeiten aus oder in Zusammenhang mit dieser Vereinbarung ist das für Graz sachlich zuständige Gericht. Diese Vereinbarung unterliegt österreichischem Recht, nicht jedoch den nichtzwingenden Verweisungsnormen des IPR. Weiter- bzw. Rückverweisungen sind ausgeschlossen. Darüber hinaus steht es PROFIT PLANET frei, den VP auch seinem allgemeinen Gerichtsstand zu klagen.</p>
|
||||||
|
<div class="signatures">
|
||||||
|
<div class="signature" style="flex:1;text-align:center;">
|
||||||
|
<p style="margin:0 0 6px;">Für PROFIT PLANET (Auftraggeber)</p>
|
||||||
|
<!-- CHANGED: wrap stamp + date in a flex column with spacing to avoid overlap -->
|
||||||
|
<div class="sig-block" style="display:flex;flex-direction:column;align-items:center;gap:6px;min-height:140px;">
|
||||||
|
<div class="pp-stamp" style="display:block;max-width:220px;margin:0 auto 6px;">{{profitplanetSignature}}</div>
|
||||||
|
<div class="sig-date" style="font-size:0.75em;line-height:1.2;">{{currentDate}}</div>
|
||||||
|
</div>
|
||||||
|
<p style="margin:0 0 6px;">Datum, Unterschrift</p>
|
||||||
|
</div>
|
||||||
|
<div class="signature">
|
||||||
|
<p style="margin:0 0 6px;">Für den VP (Auftragnehmer)</p>
|
||||||
|
<div class="sig-block">
|
||||||
|
<span class="sig-image">{{signatureImage}}</span>
|
||||||
|
<div style="font-size:0.75em;line-height:1.2;">{{fullName}}</div>
|
||||||
|
<div style="font-size:0.75em;line-height:1.2;">{{currentDate}}</div>
|
||||||
|
</div>
|
||||||
|
<p style="margin:0 0 6px;">Name, Datum, Unterschrift</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../database/UnitOfWork');
|
||||||
const RateLimitRepository = require('../repositories/RateLimitRepository');
|
const RateLimitRepository = require('../repositories/rateLimit/RateLimitRepository');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for rate limiter middleware.
|
* Factory for rate limiter middleware.
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class AdminRepository {
|
class AdminRepository {
|
||||||
static async getUserStats(conn) {
|
static async getUserStats(conn) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserDocumentRepository {
|
class UserDocumentRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class EmailVerificationRepository {
|
class EmailVerificationRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class LoginRepository {
|
class LoginRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class PasswordResetRepository {
|
class PasswordResetRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const Permission = require('../models/Permission');
|
const Permission = require('../../models/Permission');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class PermissionRepository {
|
class PermissionRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class RateLimitRepository {
|
class RateLimitRepository {
|
||||||
constructor(connection) {
|
constructor(connection) {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const ReferralToken = require('../models/ReferralToken');
|
const ReferralToken = require('../../models/ReferralToken');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class ReferralTokenRepository {
|
class ReferralTokenRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserSettingsRepository {
|
class UserSettingsRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const db = require('../database/database');
|
const db = require('../../database/database');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class CompanyStampRepository {
|
class CompanyStampRepository {
|
||||||
async create(data, conn) {
|
async create(data, conn) {
|
||||||
@ -1,4 +1,4 @@
|
|||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserStatusRepository {
|
class UserStatusRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -95,6 +95,5 @@ class UserStatusRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No changes required for progress calculation, as getStatusByUserId returns all needed fields.
|
|
||||||
|
|
||||||
module.exports = UserStatusRepository;
|
module.exports = UserStatusRepository;
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const db = require('../database/database');
|
const db = require('../../database/database');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class DocumentTemplateRepository {
|
class DocumentTemplateRepository {
|
||||||
async create(data, conn) {
|
async create(data, conn) {
|
||||||
@ -1,7 +1,7 @@
|
|||||||
const PersonalUser = require('../models/PersonalUser');
|
const PersonalUser = require('../../models/PersonalUser');
|
||||||
const CompanyUser = require('../models/CompanyUser');
|
const CompanyUser = require('../../models/CompanyUser');
|
||||||
const User = require('../models/User');
|
const User = require('../../models/User');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserRepository {
|
class UserRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -369,6 +369,46 @@ class UserRepository {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getStatusByUserId(userId) {
|
||||||
|
logger.info('UserRepository.getStatusByUserId:start', { userId });
|
||||||
|
try {
|
||||||
|
const conn = this.unitOfWork.connection;
|
||||||
|
const [rows] = await conn.query(
|
||||||
|
`SELECT
|
||||||
|
email_verified,
|
||||||
|
documents_uploaded,
|
||||||
|
profile_completed,
|
||||||
|
contract_signed,
|
||||||
|
is_admin_verified,
|
||||||
|
email_verified_at,
|
||||||
|
documents_uploaded_at,
|
||||||
|
profile_completed_at,
|
||||||
|
contract_signed_at
|
||||||
|
FROM user_status WHERE user_id = ? LIMIT 1`, [userId]
|
||||||
|
);
|
||||||
|
if (rows.length) {
|
||||||
|
const row = rows[0];
|
||||||
|
logger.info('UserRepository.getStatusByUserId:success', { userId, status: row });
|
||||||
|
return {
|
||||||
|
email_verified: row.email_verified,
|
||||||
|
documents_uploaded: row.documents_uploaded,
|
||||||
|
profile_completed: row.profile_completed,
|
||||||
|
contract_signed: row.contract_signed,
|
||||||
|
is_admin_verified: row.is_admin_verified,
|
||||||
|
email_verified_at: row.email_verified_at,
|
||||||
|
documents_uploaded_at: row.documents_uploaded_at,
|
||||||
|
profile_completed_at: row.profile_completed_at,
|
||||||
|
contract_signed_at: row.contract_signed_at
|
||||||
|
};
|
||||||
|
}
|
||||||
|
logger.info('UserRepository.getStatusByUserId:not_found', { userId });
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('UserRepository.getStatusByUserId:error', { userId, error: error.message });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = UserRepository;
|
module.exports = UserRepository;
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const CompanyUser = require('../models/CompanyUser');
|
const CompanyUser = require('../../../models/CompanyUser');
|
||||||
const User = require('../models/User');
|
const User = require('../../../models/User');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class CompanyUserRepository {
|
class CompanyUserRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,7 +1,7 @@
|
|||||||
const db = require('../database/database');
|
const db = require('../../../database/database');
|
||||||
const PersonalUser = require('../models/PersonalUser');
|
const PersonalUser = require('../../../models/PersonalUser');
|
||||||
const User = require('../models/User');
|
const User = require('../../../models/User');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class PersonalUserRepository {
|
class PersonalUserRepository {
|
||||||
constructor(unitOfWork) {
|
constructor(unitOfWork) {
|
||||||
@ -1,76 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const AdminUserController = require('../controller/admin/AdminUserController');
|
|
||||||
const UserDocumentController = require('../controller/documents/UserDocumentController');
|
|
||||||
const ServerStatusController = require('../controller/admin/ServerStatusController');
|
|
||||||
const PasswordResetController = require('../controller/password-reset/PasswordResetController');
|
|
||||||
|
|
||||||
// Helper middleware to check admin role
|
|
||||||
function requireAdmin(req, res, next) {
|
|
||||||
if (!req.user || req.user.role !== 'admin') {
|
|
||||||
return res.status(403).json({ success: false, message: 'Forbidden: Admins only.' });
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
router.get('/admin/user-stats', authMiddleware, requireAdmin, AdminUserController.getUserStats);
|
|
||||||
router.get('/admin/user-list', authMiddleware, requireAdmin, AdminUserController.getUserList);
|
|
||||||
router.get('/admin/verification-pending-users', authMiddleware, requireAdmin, AdminUserController.getVerificationPendingUsers);
|
|
||||||
router.post('/admin/verify-user/:id', authMiddleware, requireAdmin, AdminUserController.verifyUser);
|
|
||||||
router.get('/admin/user/:id/documents', authMiddleware, requireAdmin, UserDocumentController.getAllDocumentsForUser);
|
|
||||||
router.get('/admin/server-status', authMiddleware, requireAdmin, ServerStatusController.getStatus);
|
|
||||||
|
|
||||||
// PUT /admin/users/:id/permissions - update user permissions
|
|
||||||
router.put(
|
|
||||||
'/admin/users/:id/permissions',
|
|
||||||
authMiddleware,
|
|
||||||
requireAdmin,
|
|
||||||
AdminUserController.updateUserPermissions
|
|
||||||
);
|
|
||||||
|
|
||||||
// Admin: send password reset link for a user
|
|
||||||
router.post(
|
|
||||||
'/admin/send-password-reset/:userId',
|
|
||||||
authMiddleware,
|
|
||||||
requireAdmin,
|
|
||||||
async (req, res) => {
|
|
||||||
// Find user by ID and get their email
|
|
||||||
const userId = req.params.userId;
|
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
|
||||||
const PersonalUserRepository = require('../repositories/PersonalUserRepository');
|
|
||||||
const CompanyUserRepository = require('../repositories/CompanyUserRepository');
|
|
||||||
const uow = new UnitOfWork();
|
|
||||||
let user = null;
|
|
||||||
let email = null;
|
|
||||||
try {
|
|
||||||
await uow.start();
|
|
||||||
const personalRepo = new PersonalUserRepository(uow);
|
|
||||||
const companyRepo = new CompanyUserRepository(uow);
|
|
||||||
user = await personalRepo.findById(userId);
|
|
||||||
if (!user) user = await companyRepo.findById(userId);
|
|
||||||
if (!user) {
|
|
||||||
await uow.rollback();
|
|
||||||
return res.status(404).json({ success: false, message: 'User not found.' });
|
|
||||||
}
|
|
||||||
email = user.email;
|
|
||||||
await uow.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await uow.rollback();
|
|
||||||
console.error('[ADMIN SEND PASSWORD RESET] Error:', err); // <-- log error details
|
|
||||||
return res.status(500).json({ success: false, message: 'Internal server error.' });
|
|
||||||
}
|
|
||||||
// Call the password reset controller
|
|
||||||
req.body = { email }; // Set email in body for controller
|
|
||||||
return PasswordResetController.requestPasswordReset(req, res);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.delete(
|
|
||||||
'/admin/user/:id',
|
|
||||||
authMiddleware,
|
|
||||||
requireAdmin,
|
|
||||||
AdminUserController.deleteUser
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const LoginController = require('../controller/auth/LoginController');
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const UserStatusController = require('../controller/auth/UserStatusController');
|
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
|
||||||
const UserRepository = require('../repositories/UserRepository');
|
|
||||||
const EmailVerificationController = require('../controller/auth/EmailVerificationController');
|
|
||||||
const UserController = require('../controller/auth/UserController');
|
|
||||||
const UserSettingsController = require('../controller/auth/UserSettingsController'); // Add this line
|
|
||||||
const PermissionController = require('../controller/permissions/PermissionController');
|
|
||||||
const AdminUserController = require('../controller/admin/AdminUserController'); // Import the AdminUserController
|
|
||||||
const PasswordResetController = require('../controller/password-reset/PasswordResetController');
|
|
||||||
const { createRateLimiter } = require('../middleware/rateLimiter');
|
|
||||||
|
|
||||||
// Login route
|
|
||||||
router.post('/login', LoginController.login);
|
|
||||||
|
|
||||||
// Refresh token route
|
|
||||||
router.post('/refresh', LoginController.refresh);
|
|
||||||
|
|
||||||
// Logout route
|
|
||||||
router.post('/logout', LoginController.logout);
|
|
||||||
|
|
||||||
// Get current authenticated user info
|
|
||||||
router.get('/me', authMiddleware, UserController.getMe);
|
|
||||||
|
|
||||||
// Secure endpoint to get current user's status
|
|
||||||
router.get('/user/status', authMiddleware, UserStatusController.getStatus);
|
|
||||||
|
|
||||||
// New endpoint for user status progress
|
|
||||||
router.get('/user/status-progress', authMiddleware, UserStatusController.getStatusProgress);
|
|
||||||
|
|
||||||
// Add this route for full user data by id
|
|
||||||
router.get('/users/:id/full', authMiddleware, UserController.getFullUserData);
|
|
||||||
|
|
||||||
// Send verification email
|
|
||||||
router.post('/send-verification-email', authMiddleware, EmailVerificationController.sendVerificationEmail);
|
|
||||||
|
|
||||||
// Verify email code
|
|
||||||
router.post('/verify-email-code', authMiddleware, EmailVerificationController.verifyEmailCode);
|
|
||||||
|
|
||||||
// Add user settings route
|
|
||||||
router.get('/user/settings', authMiddleware, UserSettingsController.getSettings); // Add this line
|
|
||||||
|
|
||||||
router.get('/users/:id/permissions', authMiddleware, (req, res, next) => {
|
|
||||||
console.log('[ROUTE] /users/:id/permissions called');
|
|
||||||
console.log('Request method:', req.method);
|
|
||||||
console.log('Request URL:', req.originalUrl);
|
|
||||||
console.log('Request params:', req.params);
|
|
||||||
console.log('Request body:', req.body);
|
|
||||||
console.log('Request headers:', req.headers);
|
|
||||||
next();
|
|
||||||
}, PermissionController.getUserPermissions); // Add this route
|
|
||||||
|
|
||||||
// Add admin-only route for fetching full user account details
|
|
||||||
router.get('/admin/users/:id/full', authMiddleware, AdminUserController.getFullUserAccountDetails); // Add this line
|
|
||||||
|
|
||||||
router.get('/users/:id/documents', authMiddleware, UserController.getUserDocumentsAndContracts); // Add this line
|
|
||||||
|
|
||||||
// Password reset request (rate limited)
|
|
||||||
router.post(
|
|
||||||
'/request-password-reset',
|
|
||||||
createRateLimiter({
|
|
||||||
keyGenerator: req => `pwreset:${req.ip}`,
|
|
||||||
max: 5,
|
|
||||||
windowSeconds: 3600
|
|
||||||
}),
|
|
||||||
PasswordResetController.requestPasswordReset
|
|
||||||
);
|
|
||||||
|
|
||||||
// Password reset token verification
|
|
||||||
router.get('/verify-password-reset', PasswordResetController.verifyPasswordResetToken);
|
|
||||||
|
|
||||||
// Password reset (submit new password)
|
|
||||||
router.post('/reset-password', PasswordResetController.resetPassword);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const auth = require('../middleware/authMiddleware');
|
|
||||||
const ctrl = require('../controller/companyStamp/CompanyStampController');
|
|
||||||
|
|
||||||
function adminOnly(req, res, next) {
|
|
||||||
if (!req.user || !['admin','super_admin'].includes(req.user.role)) {
|
|
||||||
return res.status(403).json({ error: 'Admin role required' });
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// NEW: ensure service sees a "company" user_type for admin users
|
|
||||||
function forceCompanyForAdmin(req, res, next) {
|
|
||||||
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
|
||||||
req.user.user_type = 'company'; // mimic company to satisfy service checks
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: For primary company (id=1) only one stamp is allowed. Uploading again returns 409 with existing preview.
|
|
||||||
router.post('/company-stamps', auth, adminOnly, forceCompanyForAdmin, ctrl.upload);
|
|
||||||
router.get('/company-stamps/mine', auth, adminOnly, forceCompanyForAdmin, ctrl.listMine);
|
|
||||||
router.get('/company-stamps/mine/active', auth, adminOnly, forceCompanyForAdmin, ctrl.activeMine);
|
|
||||||
router.patch('/company-stamps/:id/activate', auth, adminOnly, forceCompanyForAdmin, ctrl.activate);
|
|
||||||
router.delete('/company-stamps/:id', auth, adminOnly, forceCompanyForAdmin, ctrl.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Mount example (in main app):
|
|
||||||
const companyStampRoutes = require('./routes/companyStamps');
|
|
||||||
app.use('/api', companyStampRoutes);
|
|
||||||
*/
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const path = require('path');
|
|
||||||
const router = express.Router();
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
|
|
||||||
// GET /api/contracts/personal
|
|
||||||
router.get('/contracts/personal', authMiddleware, (req, res) => {
|
|
||||||
const filePath = path.join(__dirname, '../contractTemplates/personal/test.pdf');
|
|
||||||
res.download(filePath, 'personal-service-contract.pdf', (err) => {
|
|
||||||
if (err) {
|
|
||||||
res.status(404).json({ success: false, message: 'Personal contract not found' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// GET /api/contracts/company
|
|
||||||
router.get('/contracts/company', authMiddleware, (req, res) => {
|
|
||||||
const filePath = path.join(__dirname, '../contractTemplates/company/test.pdf');
|
|
||||||
res.download(filePath, 'company-service-contract.pdf', (err) => {
|
|
||||||
if (err) {
|
|
||||||
res.status(404).json({ success: false, message: 'Company contract not found' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
32
routes/deleteRoutes.js
Normal file
32
routes/deleteRoutes.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
|
const AdminUserController = require('../controller/admin/AdminUserController');
|
||||||
|
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
||||||
|
const CompanyStampController = require('../controller/companyStamp/CompanyStampController');
|
||||||
|
|
||||||
|
// Helper middlewares for company-stamp
|
||||||
|
function adminOnly(req, res, next) {
|
||||||
|
if (!req.user || !['admin','super_admin'].includes(req.user.role)) {
|
||||||
|
return res.status(403).json({ error: 'Admin role required' });
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
function forceCompanyForAdmin(req, res, next) {
|
||||||
|
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
||||||
|
req.user.user_type = 'company';
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// DELETE /admin/user/:id (moved from routes/admin.js)
|
||||||
|
router.delete('/admin/user/:id', authMiddleware, AdminUserController.deleteUser);
|
||||||
|
|
||||||
|
// DELETE /document-templates/:id (moved from routes/documentTemplates.js)
|
||||||
|
router.delete('/document-templates/:id', authMiddleware, DocumentTemplateController.deleteTemplate);
|
||||||
|
|
||||||
|
// Company-stamp DELETE
|
||||||
|
router.delete('/company-stamps/:id', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.delete);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@ -1,85 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const multer = require('multer');
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
|
||||||
|
|
||||||
// Use memory storage for multer (files will be available as buffers)
|
|
||||||
const upload = multer({ storage: multer.memoryStorage() });
|
|
||||||
|
|
||||||
// Role check middleware for admin/super_admin
|
|
||||||
function adminOnly(req, res, next) {
|
|
||||||
if (!req.user || !['admin', 'super_admin'].includes(req.user.role)) {
|
|
||||||
return res.status(403).json({ error: 'Forbidden: Admins only' });
|
|
||||||
}
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
|
|
||||||
// List all templates
|
|
||||||
router.get('/document-templates', authMiddleware, DocumentTemplateController.listTemplates);
|
|
||||||
|
|
||||||
// Upload a new template
|
|
||||||
router.post(
|
|
||||||
'/document-templates',
|
|
||||||
authMiddleware,
|
|
||||||
upload.single('file'), // file field for template file
|
|
||||||
DocumentTemplateController.uploadTemplate
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get a template by ID
|
|
||||||
router.get('/document-templates/:id', authMiddleware, DocumentTemplateController.getTemplate);
|
|
||||||
|
|
||||||
// Update an existing template (edit/upload new version)
|
|
||||||
router.put(
|
|
||||||
'/document-templates/:id',
|
|
||||||
authMiddleware,
|
|
||||||
upload.single('file'), // optional new file
|
|
||||||
DocumentTemplateController.updateTemplate
|
|
||||||
);
|
|
||||||
|
|
||||||
// Delete a template by ID
|
|
||||||
router.delete('/document-templates/:id', authMiddleware, DocumentTemplateController.deleteTemplate);
|
|
||||||
|
|
||||||
// Public route: List all templates for dashboard (admin only)
|
|
||||||
router.get('/document-templates-public', authMiddleware, adminOnly, DocumentTemplateController.listTemplatesPublic);
|
|
||||||
|
|
||||||
// Update template state (active/inactive)
|
|
||||||
router.patch(
|
|
||||||
'/document-templates/:id/state',
|
|
||||||
authMiddleware,
|
|
||||||
adminOnly,
|
|
||||||
DocumentTemplateController.updateTemplateState
|
|
||||||
);
|
|
||||||
|
|
||||||
// List templates with optional state filter (admin only)
|
|
||||||
router.get('/api/document-templates', authMiddleware, adminOnly, DocumentTemplateController.listTemplatesFiltered);
|
|
||||||
|
|
||||||
// Generate PDF from template
|
|
||||||
router.get(
|
|
||||||
'/document-templates/:id/generate-pdf',
|
|
||||||
authMiddleware,
|
|
||||||
DocumentTemplateController.generatePdf
|
|
||||||
);
|
|
||||||
|
|
||||||
// Serve sanitized HTML preview (avoids direct S3 CORS)
|
|
||||||
router.get(
|
|
||||||
'/document-templates/:id/preview',
|
|
||||||
authMiddleware,
|
|
||||||
DocumentTemplateController.previewTemplate
|
|
||||||
);
|
|
||||||
|
|
||||||
// Download PDF (sanitized: template variables emptied for download)
|
|
||||||
router.get(
|
|
||||||
'/document-templates/:id/download-pdf',
|
|
||||||
authMiddleware,
|
|
||||||
DocumentTemplateController.downloadPdf
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate PDF with signature
|
|
||||||
router.post(
|
|
||||||
'/document-templates/:id/generate-pdf-with-signature',
|
|
||||||
authMiddleware,
|
|
||||||
DocumentTemplateController.generatePdfWithSignature
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const multer = require('multer');
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const PersonalDocumentController = require('../controller/documents/PersonalDocumentController');
|
|
||||||
const CompanyDocumentController = require('../controller/documents/CompanyDocumentController');
|
|
||||||
const ContractUploadController = require('../controller/documents/ContractUploadController');
|
|
||||||
|
|
||||||
// Use memory storage for multer (files will be available as buffers)
|
|
||||||
const upload = multer({ storage: multer.memoryStorage() });
|
|
||||||
|
|
||||||
// POST /api/upload/personal-id
|
|
||||||
router.post(
|
|
||||||
'/upload/personal-id',
|
|
||||||
authMiddleware,
|
|
||||||
upload.fields([
|
|
||||||
{ name: 'front', maxCount: 1 },
|
|
||||||
{ name: 'back', maxCount: 1 }
|
|
||||||
]),
|
|
||||||
PersonalDocumentController.uploadPersonalId
|
|
||||||
);
|
|
||||||
|
|
||||||
// POST /api/upload/company-id
|
|
||||||
router.post(
|
|
||||||
'/upload/company-id',
|
|
||||||
authMiddleware,
|
|
||||||
upload.fields([
|
|
||||||
{ name: 'front', maxCount: 1 },
|
|
||||||
{ name: 'back', maxCount: 1 }
|
|
||||||
]),
|
|
||||||
CompanyDocumentController.uploadCompanyId
|
|
||||||
);
|
|
||||||
|
|
||||||
// Contract upload endpoints (PDF only)
|
|
||||||
router.post(
|
|
||||||
'/upload/contract/personal',
|
|
||||||
authMiddleware,
|
|
||||||
upload.single('contract'),
|
|
||||||
ContractUploadController.uploadPersonalContract
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/upload/contract/company',
|
|
||||||
authMiddleware,
|
|
||||||
upload.single('contract'),
|
|
||||||
ContractUploadController.uploadCompanyContract
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,11 +1,99 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
const path = require('path');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
console.log('🛣️ Setting up GET routes');
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
|
const UserSettingsController = require('../controller/auth/UserSettingsController');
|
||||||
|
const ReferralTokenController = require('../controller/referral/ReferralTokenController');
|
||||||
|
const ReferralRegistrationController = require('../controller/referral/ReferralRegistrationController');
|
||||||
|
const PermissionController = require('../controller/permissions/PermissionController');
|
||||||
|
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
||||||
|
const AdminUserController = require('../controller/admin/AdminUserController');
|
||||||
|
const UserDocumentController = require('../controller/documents/UserDocumentController');
|
||||||
|
const ServerStatusController = require('../controller/admin/ServerStatusController');
|
||||||
|
const UserController = require('../controller/auth/UserController');
|
||||||
|
const UserStatusController = require('../controller/auth/UserStatusController');
|
||||||
|
const CompanyStampController = require('../controller/companyStamp/CompanyStampController'); // <-- added
|
||||||
|
|
||||||
// Add other GET routes here as needed
|
// small helpers copied from original files
|
||||||
// Registration routes have been moved to postRoutes.js
|
function adminOnly(req, res, next) {
|
||||||
|
if (!req.user || !['admin', 'super_admin'].includes(req.user.role)) {
|
||||||
|
return res.status(403).json({ error: 'Forbidden: Admins only' });
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
function requireAdmin(req, res, next) {
|
||||||
|
if (!req.user || req.user.role !== 'admin') {
|
||||||
|
return res.status(403).json({ success: false, message: 'Forbidden: Admins only.' });
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
console.log('✅ GET routes configured successfully');
|
// NEW helper used by company-stamp routes
|
||||||
|
function forceCompanyForAdmin(req, res, next) {
|
||||||
|
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
||||||
|
req.user.user_type = 'company';
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// === GET routes moved from other files ===
|
||||||
|
|
||||||
|
// auth.js GETs
|
||||||
|
router.get('/me', authMiddleware, UserController.getMe);
|
||||||
|
router.get('/user/status', authMiddleware, UserStatusController.getStatus);
|
||||||
|
router.get('/user/status-progress', authMiddleware, UserStatusController.getStatusProgress);
|
||||||
|
router.get('/users/:id/full', authMiddleware, UserController.getFullUserData);
|
||||||
|
router.get('/user/settings', authMiddleware, UserSettingsController.getSettings);
|
||||||
|
router.get('/users/:id/permissions', authMiddleware, PermissionController.getUserPermissions);
|
||||||
|
router.get('/admin/users/:id/full', authMiddleware, AdminUserController.getFullUserAccountDetails);
|
||||||
|
router.get('/users/:id/documents', authMiddleware, UserController.getUserDocumentsAndContracts);
|
||||||
|
router.get('/verify-password-reset', (req, res) => { /* Note: was moved from PasswordResetController.verifyPasswordResetToken */ res.status(204).end(); }); // keep placeholder if controller already registered via other verb
|
||||||
|
|
||||||
|
// admin.js GETs
|
||||||
|
router.get('/admin/user-stats', authMiddleware, requireAdmin, AdminUserController.getUserStats);
|
||||||
|
router.get('/admin/user-list', authMiddleware, requireAdmin, AdminUserController.getUserList);
|
||||||
|
router.get('/admin/verification-pending-users', authMiddleware, requireAdmin, AdminUserController.getVerificationPendingUsers);
|
||||||
|
router.get('/admin/user/:id/documents', authMiddleware, requireAdmin, UserDocumentController.getAllDocumentsForUser);
|
||||||
|
router.get('/admin/server-status', authMiddleware, requireAdmin, ServerStatusController.getStatus);
|
||||||
|
|
||||||
|
// permissions.js GETs
|
||||||
|
router.get('/permissions', authMiddleware, PermissionController.list);
|
||||||
|
|
||||||
|
// referral.js GETs
|
||||||
|
router.get('/referral/list', authMiddleware, ReferralTokenController.list);
|
||||||
|
router.get('/referral/stats', authMiddleware, ReferralTokenController.stats);
|
||||||
|
router.get('/referral/info/:token', ReferralRegistrationController.getReferrerInfo);
|
||||||
|
|
||||||
|
// userSettings.js GETs
|
||||||
|
router.get('/settings', authMiddleware, UserSettingsController.getSettings);
|
||||||
|
|
||||||
|
// contracts.js (file downloads)
|
||||||
|
router.get('/contracts/personal', authMiddleware, (req, res) => {
|
||||||
|
const filePath = path.join(__dirname, '../contractTemplates/personal/test.pdf');
|
||||||
|
res.download(filePath, 'personal-service-contract.pdf', (err) => {
|
||||||
|
if (err) res.status(404).json({ success: false, message: 'Personal contract not found' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
router.get('/contracts/company', authMiddleware, (req, res) => {
|
||||||
|
const filePath = path.join(__dirname, '../contractTemplates/company/test.pdf');
|
||||||
|
res.download(filePath, 'company-service-contract.pdf', (err) => {
|
||||||
|
if (err) res.status(404).json({ success: false, message: 'Company contract not found' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// documentTemplates.js GETs
|
||||||
|
router.get('/document-templates', authMiddleware, DocumentTemplateController.listTemplates);
|
||||||
|
router.get('/document-templates/:id', authMiddleware, DocumentTemplateController.getTemplate);
|
||||||
|
router.get('/document-templates-public', authMiddleware, adminOnly, DocumentTemplateController.listTemplatesPublic);
|
||||||
|
router.get('/document-templates/:id/generate-pdf', authMiddleware, DocumentTemplateController.generatePdf);
|
||||||
|
router.get('/document-templates/:id/preview', authMiddleware, DocumentTemplateController.previewTemplate);
|
||||||
|
router.get('/document-templates/:id/download-pdf', authMiddleware, DocumentTemplateController.downloadPdf);
|
||||||
|
router.get('/api/document-templates', authMiddleware, adminOnly, DocumentTemplateController.listTemplatesFiltered);
|
||||||
|
|
||||||
|
// Company-stamp GETs
|
||||||
|
router.get('/company-stamps/mine', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.listMine);
|
||||||
|
router.get('/company-stamps/mine/active', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.activeMine);
|
||||||
|
|
||||||
|
// export
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
30
routes/patchRoutes.js
Normal file
30
routes/patchRoutes.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
|
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
||||||
|
const CompanyStampController = require('../controller/companyStamp/CompanyStampController'); // <-- added
|
||||||
|
|
||||||
|
// Helper middlewares for company-stamp
|
||||||
|
function adminOnly(req, res, next) {
|
||||||
|
if (!req.user || !['admin','super_admin'].includes(req.user.role)) {
|
||||||
|
return res.status(403).json({ error: 'Admin role required' });
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
function forceCompanyForAdmin(req, res, next) {
|
||||||
|
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
||||||
|
req.user.user_type = 'company';
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PATCH /document-templates/:id/state (existing)
|
||||||
|
router.patch('/document-templates/:id/state', authMiddleware, DocumentTemplateController.updateTemplateState);
|
||||||
|
|
||||||
|
// Company-stamp PATCH (activate)
|
||||||
|
router.patch('/company-stamps/:id/activate', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.activate);
|
||||||
|
|
||||||
|
// Add other PATCH routes here as needed
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@ -1,12 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const PermissionController = require('../controller/permissions/PermissionController');
|
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
|
||||||
|
|
||||||
// GET /api/permissions - list all active permissions
|
|
||||||
router.get('/permissions', authMiddleware, PermissionController.list);
|
|
||||||
|
|
||||||
router.post('/permissions', authMiddleware, PermissionController.create);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,24 +1,131 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
|
|
||||||
|
// Controllers used by POST routes
|
||||||
|
const LoginController = require('../controller/login/LoginController');
|
||||||
|
const EmailVerificationController = require('../controller/auth/EmailVerificationController');
|
||||||
|
const PasswordResetController = require('../controller/password-reset/PasswordResetController');
|
||||||
|
const ReferralTokenController = require('../controller/referral/ReferralTokenController');
|
||||||
|
const ReferralRegistrationController = require('../controller/referral/ReferralRegistrationController');
|
||||||
|
const PermissionController = require('../controller/permissions/PermissionController');
|
||||||
|
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
||||||
const PersonalRegisterController = require('../controller/register/PersonalRegisterController');
|
const PersonalRegisterController = require('../controller/register/PersonalRegisterController');
|
||||||
const CompanyRegisterController = require('../controller/register/CompanyRegisterController');
|
const CompanyRegisterController = require('../controller/register/CompanyRegisterController');
|
||||||
|
const PersonalDocumentController = require('../controller/documents/PersonalDocumentController');
|
||||||
|
const CompanyDocumentController = require('../controller/documents/CompanyDocumentController');
|
||||||
|
const ContractUploadController = require('../controller/documents/ContractUploadController');
|
||||||
|
const PersonalProfileController = require('../controller/profile/PersonalProfileController');
|
||||||
|
const CompanyProfileController = require('../controller/profile/CompanyProfileController');
|
||||||
|
const AdminUserController = require('../controller/admin/AdminUserController');
|
||||||
|
const CompanyStampController = require('../controller/companyStamp/CompanyStampController'); // <-- added
|
||||||
|
|
||||||
console.log('🛣️ Setting up POST routes for registration');
|
const multer = require('multer');
|
||||||
|
const upload = multer({ storage: multer.memoryStorage() });
|
||||||
|
|
||||||
// Personal user registration route
|
console.log('🛣️ Setting up POST routes');
|
||||||
router.post('/register/personal', (req, res) => {
|
|
||||||
console.log('🔗 POST /register/personal route accessed');
|
// auth POSTs (moved from routes/auth.js)
|
||||||
console.log('📦 Expected data structure: firstName, lastName, email, confirmEmail, phone, password, confirmPassword, referralEmail');
|
router.post('/login', LoginController.login);
|
||||||
PersonalRegisterController.register(req, res);
|
router.post('/refresh', LoginController.refresh);
|
||||||
|
router.post('/logout', LoginController.logout);
|
||||||
|
router.post('/send-verification-email', authMiddleware, EmailVerificationController.sendVerificationEmail);
|
||||||
|
router.post('/verify-email-code', authMiddleware, EmailVerificationController.verifyEmailCode);
|
||||||
|
|
||||||
|
// Password reset POSTs (moved)
|
||||||
|
router.post(
|
||||||
|
'/request-password-reset',
|
||||||
|
PasswordResetController.requestPasswordReset
|
||||||
|
);
|
||||||
|
router.post('/reset-password', PasswordResetController.resetPassword);
|
||||||
|
|
||||||
|
// Referral POSTs (moved from routes/referral.js)
|
||||||
|
router.post('/referral/create', authMiddleware, ReferralTokenController.create);
|
||||||
|
router.post('/referral/deactivate', authMiddleware, ReferralTokenController.deactivate);
|
||||||
|
router.post('/register/personal-referral', ReferralRegistrationController.registerPersonalReferral);
|
||||||
|
router.post('/register/company-referral', ReferralRegistrationController.registerCompanyReferral);
|
||||||
|
|
||||||
|
// Permissions POST (moved from routes/permissions.js)
|
||||||
|
router.post('/permissions', authMiddleware, PermissionController.create);
|
||||||
|
|
||||||
|
// Document templates upload & signature generation POSTs (moved)
|
||||||
|
router.post('/document-templates', authMiddleware, upload.single('file'), DocumentTemplateController.uploadTemplate);
|
||||||
|
router.post('/document-templates/:id/generate-pdf-with-signature', authMiddleware, DocumentTemplateController.generatePdfWithSignature);
|
||||||
|
|
||||||
|
// Document uploads (moved from routes/documents.js)
|
||||||
|
router.post('/upload/personal-id', authMiddleware, upload.fields([{ name: 'front', maxCount: 1 }, { name: 'back', maxCount: 1 }]), PersonalDocumentController.uploadPersonalId);
|
||||||
|
router.post('/upload/company-id', authMiddleware, upload.fields([{ name: 'front', maxCount: 1 }, { name: 'back', maxCount: 1 }]), CompanyDocumentController.uploadCompanyId);
|
||||||
|
router.post('/upload/contract/personal', authMiddleware, upload.single('contract'), ContractUploadController.uploadPersonalContract);
|
||||||
|
router.post('/upload/contract/company', authMiddleware, upload.single('contract'), ContractUploadController.uploadCompanyContract);
|
||||||
|
|
||||||
|
// Profile completion POSTs (moved from routes/profile.js)
|
||||||
|
router.post('/profile/personal/complete', authMiddleware, PersonalProfileController.completeProfile);
|
||||||
|
router.post('/profile/company/complete', authMiddleware, CompanyProfileController.completeProfile);
|
||||||
|
|
||||||
|
// Admin POSTs (moved from routes/admin.js)
|
||||||
|
router.post('/admin/verify-user/:id', authMiddleware, AdminUserController.verifyUser);
|
||||||
|
router.post('/admin/send-password-reset/:userId', authMiddleware, async (req, res) => {
|
||||||
|
const userId = req.params.userId;
|
||||||
|
// require here to avoid circular/top-level ordering issues
|
||||||
|
const UnitOfWork = require('../database/UnitOfWork');
|
||||||
|
const PersonalUserRepository = require('../repositories/user/personal/PersonalUserRepository');
|
||||||
|
const CompanyUserRepository = require('../repositories/user/company/CompanyUserRepository');
|
||||||
|
|
||||||
|
const uow = new UnitOfWork();
|
||||||
|
let user = null;
|
||||||
|
try {
|
||||||
|
await uow.start();
|
||||||
|
const personalRepo = new PersonalUserRepository(uow);
|
||||||
|
const companyRepo = new CompanyUserRepository(uow);
|
||||||
|
user = await personalRepo.findById(userId);
|
||||||
|
if (!user) user = await companyRepo.findById(userId);
|
||||||
|
if (!user) {
|
||||||
|
await uow.rollback();
|
||||||
|
return res.status(404).json({ success: false, message: 'User not found.' });
|
||||||
|
}
|
||||||
|
const email = user.email;
|
||||||
|
await uow.commit();
|
||||||
|
|
||||||
|
// forward to PasswordResetController using same interface as original route
|
||||||
|
req.body = { email };
|
||||||
|
return PasswordResetController.requestPasswordReset(req, res);
|
||||||
|
} catch (err) {
|
||||||
|
try { await uow.rollback(); } catch (_) {}
|
||||||
|
console.error('[ADMIN SEND PASSWORD RESET] Error:', err);
|
||||||
|
return res.status(500).json({ success: false, message: 'Internal server error.' });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Company user registration route
|
// Helper middleware for company-stamp routes
|
||||||
|
function adminOnly(req, res, next) {
|
||||||
|
if (!req.user || !['admin','super_admin'].includes(req.user.role)) {
|
||||||
|
return res.status(403).json({ error: 'Admin role required' });
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEW: ensure service sees a "company" user_type for admin users
|
||||||
|
function forceCompanyForAdmin(req, res, next) {
|
||||||
|
if (req.user && ['admin','super_admin'].includes(req.user.role) && req.user.user_type !== 'company') {
|
||||||
|
req.user.user_type = 'company'; // mimic company to satisfy service checks
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Company-stamp POST
|
||||||
|
router.post('/company-stamps', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.upload);
|
||||||
|
|
||||||
|
// Existing registration handlers (keep)
|
||||||
|
router.post('/register/personal', (req, res) => {
|
||||||
|
console.log('🔗 POST /register/personal route accessed');
|
||||||
|
PersonalRegisterController.register(req, res);
|
||||||
|
});
|
||||||
router.post('/register/company', (req, res) => {
|
router.post('/register/company', (req, res) => {
|
||||||
console.log('🔗 POST /register/company route accessed');
|
console.log('🔗 POST /register/company route accessed');
|
||||||
console.log('📦 Expected data structure: companyName, companyEmail, confirmCompanyEmail, companyPhone, contactPersonName, contactPersonPhone, password, confirmPassword');
|
|
||||||
CompanyRegisterController.register(req, res);
|
CompanyRegisterController.register(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ POST registration routes configured successfully');
|
console.log('✅ POST routes configured successfully');
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const PersonalProfileController = require('../controller/profile/PersonalProfileController');
|
|
||||||
const CompanyProfileController = require('../controller/profile/CompanyProfileController');
|
|
||||||
|
|
||||||
// POST /api/profile/personal/complete
|
|
||||||
router.post('/profile/personal/complete', authMiddleware, PersonalProfileController.completeProfile);
|
|
||||||
|
|
||||||
// POST /api/profile/company/complete
|
|
||||||
router.post('/profile/company/complete', authMiddleware, CompanyProfileController.completeProfile);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
16
routes/putRoutes.js
Normal file
16
routes/putRoutes.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const authMiddleware = require('../middleware/authMiddleware');
|
||||||
|
const AdminUserController = require('../controller/admin/AdminUserController');
|
||||||
|
const DocumentTemplateController = require('../controller/documentTemplate/DocumentTemplateController');
|
||||||
|
const multer = require('multer');
|
||||||
|
const upload = multer({ storage: multer.memoryStorage() });
|
||||||
|
|
||||||
|
// PUT /admin/users/:id/permissions (moved from routes/admin.js)
|
||||||
|
router.put('/admin/users/:id/permissions', authMiddleware, AdminUserController.updateUserPermissions);
|
||||||
|
|
||||||
|
// PUT /document-templates/:id (moved from routes/documentTemplates.js)
|
||||||
|
router.put('/document-templates/:id', authMiddleware, upload.single('file'), DocumentTemplateController.updateTemplate);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@ -1,15 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const ReferralTokenController = require('../controller/referral/ReferralTokenController');
|
|
||||||
const ReferralRegistrationController = require('../controller/referral/ReferralRegistrationController');
|
|
||||||
|
|
||||||
router.post('/referral/create', authMiddleware, ReferralTokenController.create);
|
|
||||||
router.get('/referral/list', authMiddleware, ReferralTokenController.list);
|
|
||||||
router.get('/referral/stats', authMiddleware, ReferralTokenController.stats);
|
|
||||||
router.post('/referral/deactivate', authMiddleware, ReferralTokenController.deactivate);
|
|
||||||
router.get('/referral/info/:token', ReferralRegistrationController.getReferrerInfo);
|
|
||||||
router.post('/register/personal-referral', ReferralRegistrationController.registerPersonalReferral);
|
|
||||||
router.post('/register/company-referral', ReferralRegistrationController.registerCompanyReferral);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const router = express.Router();
|
|
||||||
const authMiddleware = require('../middleware/authMiddleware');
|
|
||||||
const UserSettingsController = require('../controller/auth/UserSettingsController');
|
|
||||||
|
|
||||||
router.get('/settings', authMiddleware, UserSettingsController.getSettings);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const db = require('../database/database'); // Adjust path if needed
|
const db = require('../database/database'); // Adjust path if needed
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../database/UnitOfWork');
|
||||||
const argon2 = require('argon2');
|
const argon2 = require('argon2');
|
||||||
|
|
||||||
async function createAdminUser() {
|
async function createAdminUser() {
|
||||||
|
|||||||
45
server.js
45
server.js
@ -2,26 +2,16 @@ require('dotenv').config();
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
const { createDatabase } = require('./database/createDb');
|
const { createDatabase } = require('./database/createDb');
|
||||||
const getRoutes = require('./routes/getRoutes');
|
|
||||||
const postRoutes = require('./routes/postRoutes');
|
|
||||||
const authRoutes = require('./routes/auth');
|
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const authMiddleware = require('./middleware/authMiddleware');
|
const authMiddleware = require('./middleware/authMiddleware');
|
||||||
const documentsRoutes = require('./routes/documents');
|
|
||||||
const profileRoutes = require('./routes/profile');
|
|
||||||
const contractsRoutes = require('./routes/contracts');
|
|
||||||
const referralRoutes = require('./routes/referral');
|
|
||||||
const permissionsRoutes = require('./routes/permissions');
|
|
||||||
const permissionsInit = require('./scripts/initPermissions');
|
|
||||||
const adminRoutes = require('./routes/admin');
|
|
||||||
const createAdminUser = require('./scripts/createAdminUser');
|
|
||||||
const { createRateLimiter } = require('./middleware/rateLimiter');
|
const { createRateLimiter } = require('./middleware/rateLimiter');
|
||||||
const documentTemplatesRoutes = require('./routes/documentTemplates');
|
|
||||||
const companyStampRoutes = require('./routes/companyStamps'); // NEW
|
|
||||||
|
|
||||||
// add logger (now with setters/getter)
|
// add logger (now with setters/getter)
|
||||||
const { logger, requestLogger, setLogLevel, setTransportLevel, getLoggerLevels } = require('./middleware/logger');
|
const { logger, requestLogger, setLogLevel, setTransportLevel, getLoggerLevels } = require('./middleware/logger');
|
||||||
|
|
||||||
|
// ADD: import permission initializer and admin-creation script
|
||||||
|
const permissionsInit = require('./scripts/initPermissions');
|
||||||
|
const createAdminUser = require('./scripts/createAdminUser');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3001;
|
const PORT = process.env.PORT || 3001;
|
||||||
|
|
||||||
@ -85,19 +75,20 @@ app.use('/api/protected', authMiddleware, (req, res) => {
|
|||||||
res.json({ success: true, message: 'Access granted', user: req.user });
|
res.json({ success: true, message: 'Access granted', user: req.user });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Use getRoutes for URL routing and controller references
|
// Import and mount the new verb-specific routers
|
||||||
app.use('/', getRoutes);
|
const getRoutes = require('./routes/getRoutes');
|
||||||
app.use('/', postRoutes); // <-- Add this line to enable POST /register/personal and /register/company
|
const postRoutes = require('./routes/postRoutes');
|
||||||
app.use('/api/auth', authRoutes);
|
const putRoutes = require('./routes/putRoutes');
|
||||||
app.use('/api', documentsRoutes);
|
const patchRoutes = require('./routes/patchRoutes');
|
||||||
app.use('/api', profileRoutes);
|
const deleteRoutes = require('./routes/deleteRoutes'); // added
|
||||||
app.use('/api', contractsRoutes);
|
|
||||||
app.use('/api', referralRoutes);
|
app.use('/api', getRoutes);
|
||||||
app.use('/api', permissionsRoutes);
|
app.use('/api', postRoutes);
|
||||||
app.use('/api', adminRoutes);
|
app.use('/api', putRoutes);
|
||||||
app.use('/api', documentTemplatesRoutes);
|
app.use('/api', patchRoutes);
|
||||||
app.use('/api', companyStampRoutes); // NEW
|
app.use('/api', deleteRoutes);
|
||||||
logger.info('🛣️ GET routes configured and ready');
|
|
||||||
|
logger.info('🛣️ Verb-specific routes configured and ready');
|
||||||
|
|
||||||
// Insert admin endpoint for dynamic log-level control
|
// Insert admin endpoint for dynamic log-level control
|
||||||
// Requires authenticated user and admin role
|
// Requires authenticated user and admin role
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
const AdminRepository = require('../repositories/AdminRepository');
|
const AdminRepository = require('../../repositories/admin/AdminRepository');
|
||||||
const UserDocumentRepository = require('../repositories/UserDocumentRepository');
|
const UserDocumentRepository = require('../../repositories/documents/UserDocumentRepository');
|
||||||
const UserRepository = require('../repositories/UserRepository');
|
const UserRepository = require('../../repositories/user/UserRepository');
|
||||||
const { s3 } = require('../utils/exoscaleUploader');
|
const { s3 } = require('../../utils/exoscaleUploader');
|
||||||
const { GetObjectCommand } = require('@aws-sdk/client-s3');
|
const { GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
|
||||||
const { DeleteObjectCommand } = require('@aws-sdk/client-s3');
|
const { DeleteObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
const pidusage = require('pidusage');
|
const pidusage = require('pidusage');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class AdminService {
|
class AdminService {
|
||||||
static async getUserStats(unitOfWork) {
|
static async getUserStats(unitOfWork) {
|
||||||
@ -1,12 +1,12 @@
|
|||||||
const UserDocumentRepository = require('../repositories/UserDocumentRepository');
|
const UserDocumentRepository = require('../../repositories/documents/UserDocumentRepository');
|
||||||
const { uploadBuffer } = require('../utils/exoscaleUploader');
|
const { uploadBuffer } = require('../../utils/exoscaleUploader');
|
||||||
const PDFDocument = require('pdfkit');
|
const PDFDocument = require('pdfkit');
|
||||||
const getStream = require('get-stream');
|
const getStream = require('get-stream');
|
||||||
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
|
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
|
||||||
const DocumentTemplateService = require('./DocumentTemplateService');
|
const DocumentTemplateService = require('../template/DocumentTemplateService');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
function fillTemplate(template, data) {
|
function fillTemplate(template, data) {
|
||||||
return template.replace(/{{(\w+)}}/g, (_, key) => data[key] || '');
|
return template.replace(/{{(\w+)}}/g, (_, key) => data[key] || '');
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const UserDocumentRepository = require('../repositories/UserDocumentRepository');
|
const UserDocumentRepository = require('../../../repositories/documents/UserDocumentRepository');
|
||||||
const { uploadBuffer } = require('../utils/exoscaleUploader');
|
const { uploadBuffer } = require('../../../utils/exoscaleUploader');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class CompanyDocumentService {
|
class CompanyDocumentService {
|
||||||
static async uploadCompanyId({ userId, idType, idNumber, expiryDate, files, unitOfWork }) {
|
static async uploadCompanyId({ userId, idType, idNumber, expiryDate, files, unitOfWork }) {
|
||||||
@ -61,7 +61,7 @@ class CompanyDocumentService {
|
|||||||
);
|
);
|
||||||
logger.info('CompanyDocumentService.uploadCompanyId:user_status_updated', { userId });
|
logger.info('CompanyDocumentService.uploadCompanyId:user_status_updated', { userId });
|
||||||
|
|
||||||
const UserStatusService = require('./UserStatusService');
|
const UserStatusService = require('../../status/UserStatusService');
|
||||||
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
|
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
|
||||||
logger.info('CompanyDocumentService.uploadCompanyId:pending_check_complete', { userId });
|
logger.info('CompanyDocumentService.uploadCompanyId:pending_check_complete', { userId });
|
||||||
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const UserDocumentRepository = require('../repositories/UserDocumentRepository');
|
const UserDocumentRepository = require('../../../repositories/documents/UserDocumentRepository');
|
||||||
const { uploadBuffer } = require('../utils/exoscaleUploader');
|
const { uploadBuffer } = require('../../../utils/exoscaleUploader');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class PersonalDocumentService {
|
class PersonalDocumentService {
|
||||||
static async uploadPersonalId({ userId, idType, idNumber, expiryDate, files, unitOfWork }) {
|
static async uploadPersonalId({ userId, idType, idNumber, expiryDate, files, unitOfWork }) {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const EmailVerificationRepository = require('../repositories/EmailVerificationRepository');
|
const EmailVerificationRepository = require('../../repositories/email/EmailVerificationRepository');
|
||||||
const MailService = require('./MailService');
|
const MailService = require('./MailService');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class EmailVerificationService {
|
class EmailVerificationService {
|
||||||
static async sendVerificationEmail(user, unitOfWork) {
|
static async sendVerificationEmail(user, unitOfWork) {
|
||||||
@ -74,7 +74,7 @@ class EmailVerificationService {
|
|||||||
logger.info('EmailVerificationService.verifyCode:user_status_updated', { userId });
|
logger.info('EmailVerificationService.verifyCode:user_status_updated', { userId });
|
||||||
|
|
||||||
// Check if all steps are complete and set status to 'pending' if so
|
// Check if all steps are complete and set status to 'pending' if so
|
||||||
const UserStatusService = require('./UserStatusService');
|
const UserStatusService = require('../status/UserStatusService');
|
||||||
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
|
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
|
||||||
logger.info('EmailVerificationService.verifyCode:pending_check_complete', { userId });
|
logger.info('EmailVerificationService.verifyCode:pending_check_complete', { userId });
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
const brevo = require('@getbrevo/brevo');
|
const brevo = require('@getbrevo/brevo');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class MailService {
|
class MailService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -17,7 +17,8 @@ class MailService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.loginUrl = process.env.LOGIN_URL;
|
this.loginUrl = process.env.LOGIN_URL;
|
||||||
this.templatesDir = path.join(__dirname, '../mailTemplates');
|
// Use the single correct templates directory
|
||||||
|
this.templatesDir = path.join(__dirname, '..', '..', 'mailTemplates');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to load and render a template
|
// Helper to load and render a template
|
||||||
@ -1,9 +1,9 @@
|
|||||||
const UserRepository = require('../repositories/UserRepository');
|
const UserRepository = require('../../repositories/user/UserRepository');
|
||||||
const LoginRepository = require('../repositories/LoginRepository');
|
const LoginRepository = require('../../repositories/login/LoginRepository');
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class LoginService {
|
class LoginService {
|
||||||
static async login(email, password) {
|
static async login(email, password) {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const PermissionRepository = require('../repositories/PermissionRepository');
|
const PermissionRepository = require('../../repositories/permissions/PermissionRepository');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class PermissionService {
|
class PermissionService {
|
||||||
static async getAllPermissions(unitOfWork) {
|
static async getAllPermissions(unitOfWork) {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const CompanyUserRepository = require('../repositories/CompanyUserRepository');
|
const CompanyUserRepository = require('../../../repositories/user/company/CompanyUserRepository');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class CompanyProfileService {
|
class CompanyProfileService {
|
||||||
static async completeProfile(userId, profileData, unitOfWork) {
|
static async completeProfile(userId, profileData, unitOfWork) {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const PersonalUserRepository = require('../repositories/PersonalUserRepository');
|
const PersonalUserRepository = require('../../../repositories/user/personal/PersonalUserRepository');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class PersonalProfileService {
|
class PersonalProfileService {
|
||||||
static async completeProfile(userId, profileData, unitOfWork) {
|
static async completeProfile(userId, profileData, unitOfWork) {
|
||||||
@ -10,7 +10,7 @@ class PersonalProfileService {
|
|||||||
logger.info('PersonalProfileService.completeProfile:profile_completed', { userId });
|
logger.info('PersonalProfileService.completeProfile:profile_completed', { userId });
|
||||||
|
|
||||||
// Check if all steps are complete and set status to 'pending' if so
|
// Check if all steps are complete and set status to 'pending' if so
|
||||||
const UserStatusService = require('./UserStatusService');
|
const UserStatusService = require('../../status/UserStatusService');
|
||||||
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
|
await UserStatusService.checkAndSetPendingIfComplete(userId, unitOfWork);
|
||||||
logger.info('PersonalProfileService.completeProfile:pending_check_complete', { userId });
|
logger.info('PersonalProfileService.completeProfile:pending_check_complete', { userId });
|
||||||
logger.info('PersonalProfileService.completeProfile:success', { userId });
|
logger.info('PersonalProfileService.completeProfile:success', { userId });
|
||||||
@ -1,10 +1,10 @@
|
|||||||
const ReferralTokenRepository = require('../repositories/ReferralTokenRepository');
|
const ReferralTokenRepository = require('../../repositories/referral/ReferralTokenRepository');
|
||||||
const PersonalUserRepository = require('../repositories/PersonalUserRepository');
|
const PersonalUserRepository = require('../../repositories/user/personal/PersonalUserRepository');
|
||||||
const CompanyUserRepository = require('../repositories/CompanyUserRepository');
|
const CompanyUserRepository = require('../../repositories/user/company/CompanyUserRepository');
|
||||||
const UserStatusService = require('./UserStatusService');
|
const UserStatusService = require('../status/UserStatusService');
|
||||||
const UserSettingsRepository = require('../repositories/UserSettingsRepository');
|
const UserSettingsRepository = require('../../repositories/settings/UserSettingsRepository');
|
||||||
const MailService = require('./MailService');
|
const MailService = require('../email/MailService');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class ReferralService {
|
class ReferralService {
|
||||||
// --- Token creation and management ---
|
// --- Token creation and management ---
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const CompanyStampRepository = require('../repositories/CompanyStampRepository');
|
const CompanyStampRepository = require('../../../repositories/stamp/CompanyStampRepository');
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../../../database/UnitOfWork');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
const ALLOWED_MIME = new Set(['image/png', 'image/jpeg', 'image/webp']);
|
const ALLOWED_MIME = new Set(['image/png', 'image/jpeg', 'image/webp']);
|
||||||
const MAX_IMAGE_BYTES = 500 * 1024; // 500 KB
|
const MAX_IMAGE_BYTES = 500 * 1024; // 500 KB
|
||||||
@ -1,5 +1,5 @@
|
|||||||
const UserStatusRepository = require('../repositories/UserStatusRepository');
|
const UserStatusRepository = require('../../repositories/status/UserStatusRepository');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class UserStatusService {
|
class UserStatusService {
|
||||||
static async initializeUserStatus(userId, userType, unitOfWork, status = 'inactive') {
|
static async initializeUserStatus(userId, userType, unitOfWork, status = 'inactive') {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
const DocumentTemplateRepository = require('../repositories/DocumentTemplateRepository');
|
const DocumentTemplateRepository = require('../../repositories/template/DocumentTemplateRepository');
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../../database/UnitOfWork');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../middleware/logger');
|
||||||
|
|
||||||
class DocumentTemplateService {
|
class DocumentTemplateService {
|
||||||
async listTemplates() {
|
async listTemplates() {
|
||||||
@ -1,9 +1,9 @@
|
|||||||
const CompanyUserRepository = require('../repositories/CompanyUserRepository');
|
const CompanyUserRepository = require('../../../repositories/user/company/CompanyUserRepository');
|
||||||
const UserStatusService = require('./UserStatusService');
|
const UserStatusService = require('../../status/UserStatusService');
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../../../database/UnitOfWork');
|
||||||
const CompanyUser = require('../models/CompanyUser');
|
const CompanyUser = require('../../../models/CompanyUser');
|
||||||
const MailService = require('./MailService');
|
const MailService = require('../../email/MailService');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class CompanyUserService {
|
class CompanyUserService {
|
||||||
static async createCompanyUser({ companyEmail, password, companyName, companyPhone, contactPersonName, contactPersonPhone }) {
|
static async createCompanyUser({ companyEmail, password, companyName, companyPhone, contactPersonName, contactPersonPhone }) {
|
||||||
@ -1,9 +1,9 @@
|
|||||||
const PersonalUserRepository = require('../repositories/PersonalUserRepository');
|
const PersonalUserRepository = require('../../../repositories/user/personal/PersonalUserRepository');
|
||||||
const ReferralService = require('./ReferralService');
|
const ReferralService = require('../../referral/ReferralService');
|
||||||
const UserStatusService = require('./UserStatusService');
|
const UserStatusService = require('../../status/UserStatusService');
|
||||||
const UnitOfWork = require('../repositories/UnitOfWork');
|
const UnitOfWork = require('../../../database/UnitOfWork');
|
||||||
const MailService = require('./MailService');
|
const MailService = require('../../email/MailService');
|
||||||
const { logger } = require('../middleware/logger');
|
const { logger } = require('../../../middleware/logger');
|
||||||
|
|
||||||
class PersonalUserService {
|
class PersonalUserService {
|
||||||
static async createPersonalUser({ email, password, firstName, lastName, phone, referralEmail }) {
|
static async createPersonalUser({ email, password, firstName, lastName, phone, referralEmail }) {
|
||||||
Loading…
Reference in New Issue
Block a user