--- a/db/db-schema.sql Fri Apr 27 16:18:28 2012 +0200
+++ b/db/db-schema.sql Tue May 01 21:40:36 2012 +0200
@@ -201,6 +201,10 @@
"updated_by" bigint
);
create sequence "comment_id_seq";
+create table "project_company" (
+ "project" bigint not null,
+ "company" bigint not null
+ );
-- foreign key constraints :
alter table "address" add constraint "addressFK1" foreign key ("city_id") references "city"("id");
alter table "city" add constraint "cityFK2" foreign key ("country_id") references "country"("id");
@@ -220,8 +224,11 @@
alter table "company_contact" add constraint "company_contactFK8" foreign key ("contact") references "contact"("id") on delete cascade;
alter table "user_contact" add constraint "user_contactFK9" foreign key ("entity") references "user"("id") on delete cascade;
alter table "user_contact" add constraint "user_contactFK10" foreign key ("contact") references "contact"("id") on delete cascade;
+alter table "project_company" add constraint "project_companyFK19" foreign key ("project") references "project"("id") on delete cascade;
+alter table "project_company" add constraint "project_companyFK20" foreign key ("company") references "company"("id") on delete cascade;
-- composite key indexes :
alter table "company_contact" add constraint "company_contactCPK" unique("entity","contact");
alter table "user_contact" add constraint "user_contactCPK" unique("entity","contact");
+alter table "project_company" add constraint "project_companyCPK" unique("project","company");
-- column group indexes :
create index "user_deleted_active_idx" on "user" ("deleted","active");
--- a/src/main/scala/fis/crm/ui/CompanySnippet.scala Fri Apr 27 16:18:28 2012 +0200
+++ b/src/main/scala/fis/crm/ui/CompanySnippet.scala Tue May 01 21:40:36 2012 +0200
@@ -19,6 +19,8 @@
import fis.base.ui._
import fis.crm.model._
import fis.geo.model._
+import fis.pm.model.CompanyProjects
+import fis.pm.ui.ProjectTable
import net.liftweb.common._
import net.liftweb.http._
import net.liftweb.http.js.JsCmds.RedirectTo
@@ -44,7 +46,8 @@
private val viewPre = Menu.param[Company]("company.view", l10n("Company"), parse,
encode) / prefix / * >> Title(c => i18n("Company %s", c.linkName)) >>
locTpl("company/view") >> Snippet("panel", panel) >>
- Snippet("contacts", contacts.contacts) >> Hidden
+ Snippet("contacts", contacts.contacts) >>
+ Snippet("projects", projects) >> Hidden
private val editPre = Menu.param[Company]("company.edit", l10n("Edit"), parse,
encode) / prefix / * / EDIT >>
@@ -77,6 +80,9 @@
private def panel: CssTr = "*" #> cur.map(CompanyPanel(_))
+ private def projects: CssTr = "*" #> cur.map { c =>
+ ProjectTable(CompanyProjects(c)) }
+
object url {
def view: Company => Box[String] = (viewLoc.calcHref _) andThen (Box !! _)
}
--- a/src/main/scala/fis/pm/model/PmSchema.scala Fri Apr 27 16:18:28 2012 +0200
+++ b/src/main/scala/fis/pm/model/PmSchema.scala Tue May 01 21:40:36 2012 +0200
@@ -63,6 +63,15 @@
val commentTask = oneToManyRelation(taskT, commentT).
via((t, c) => (t.id === c.task))
commentTask.foreignKeyDeclaration.constrainReference(onDelete cascade)
+
+ /* project - company */
+ val projectCompany = manyToManyRelation(projectT, companyT).
+ via[ProjectCompany]((p, c, pc) => (
+ p.id === pc.project,
+ c.id === pc.company
+ ))
+ projectCompany.leftForeignKeyDeclaration.constrainReference(onDelete cascade)
+ projectCompany.rightForeignKeyDeclaration.constrainReference(onDelete cascade)
}
object PmSchema extends PmSchema
@@ -77,4 +86,20 @@
from(PmSchema.commentTask.left(t))(c => select(c) orderBy(c.createdAt asc))
}
+object CompanyProjects {
+ import fis.crm.model.Company
+ def apply(c: Company): Iterable[Project] =
+ from(PmSchema.projectCompany.right(c))(p => select(p) orderBy(p.name asc))
+}
+
+/* Many-to-many relations */
+
+import org.squeryl.KeyedEntity
+import org.squeryl.dsl._
+
+case class ProjectCompany(val project: Long, val company: Long)
+ extends KeyedEntity[CompositeKey2[Long, Long]] {
+ def id = CompositeKey2(project, company)
+}
+
// vim: set ts=2 sw=2 et:
--- a/src/main/scala/fis/pm/ui/ProjectSnippet.scala Fri Apr 27 16:18:28 2012 +0200
+++ b/src/main/scala/fis/pm/ui/ProjectSnippet.scala Tue May 01 21:40:36 2012 +0200
@@ -16,9 +16,11 @@
package fis.pm.ui
import fis.base.ui._
+import fis.crm.model._
import fis.pm.model._
import net.liftweb.common._
import net.liftweb.http._
+import net.liftweb.record.field._
import net.liftweb.sitemap._
import net.liftweb.sitemap.Loc._
import net.liftweb.util._
@@ -85,36 +87,53 @@
def view: Project => Box[String] = (viewLoc.calcHref _) andThen (Box !! _)
}
- private def fields(p: Project) = List(p.name, p.identS, p.stateFld, p.createdBy,
- p.createdAt, p.deadline, p.responsible, p.productLine, p.description, p.note)
-
- private def formFields(p: Project) = List(p.name, p.identS, p.stateFld,
- p.deadline, p.responsible, p.productLine, p.description, p.note)
-
- private object ProjectTable extends FieldTable[Project] {
- def fields(p: Project) = EntityLink(p) ++ Seq(p.identS, p.deadline,
- p.responsible, p.description, p.note)
- def apply(l: Iterable[Project]) = build(Project, l)
- }
+ private def fields(p: Project) = List(p.name, p.identS, p.stateFld,
+ p.createdBy, p.createdAt, p.deadline, p.responsible, p.productLine,
+ ProjectCompanyField(p), p.description, p.note)
private case class ProjectLink(c: Project) extends EntityLink[Project](c, url.view)
EntityLink.register[Project](ProjectLink(_))
- private object form extends HorizontalScreen with CancelButton with SaveButton {
+ private case class ProjectCompanyField(p: Project) extends OptionalLongField(p)
+ with CompanyField with FieldLabel {
+ override def name = "company"
+ override def defaultValueBox =
+ PmSchema.projectCompany.left(p).headOption.map(_.id)
+ }
+
+ private object form extends HorizontalScreen with CancelButton with
+ SaveButton {
private object project extends ScreenVar[Project](Project.createRecord)
+ private object company extends ScreenVar[CompanyField](
+ ProjectCompanyField(project))
+
+ private def formFields(p: Project) = {
+ List(p.name, p.identS, p.stateFld, p.deadline, p.responsible,
+ p.productLine, company.get, p.description, p.note)
+ }
override def screenFields: List[BaseField] = formFields(project)
override def localSetup() {
- cur.foreach(project(_))
+ cur.foreach { p => project(p); company(ProjectCompanyField(p)) }
}
- def finish() { save(project) foreach { v =>
- S notice l10n("Project %s saved.", v.linkName)
- S.redirectTo(viewLoc.calcHref(v))
- }}
+ def finish() {
+ save(project) foreach { p =>
+ val fk = PmSchema.projectCompany.left(p)
+ company.vend match {
+ case Full(c) if fk.exists(_.id == c.id) => // empty, no update
+ case Full(c) =>
+ fk.dissociateAll
+ fk.associate(c)
+ case _ => fk.dissociateAll
+ }
+ S notice l10n("Project %s saved.", p.linkName)
+ S.redirectTo(viewLoc.calcHref(p))
+ }
+ }
}
private object deleteF extends HorizontalScreen with CancelButton with
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/fis/pm/ui/ProjectTable.scala Tue May 01 21:40:36 2012 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 Tomas Zeman <tzeman@volny.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package fis.pm.ui
+
+import fis.pm.model._
+import fis.base.ui._
+
+object ProjectTable extends FieldTable[Project] {
+ def fields(p: Project) = EntityLink(p) ++ Seq(p.identS, p.deadline,
+ p.responsible, p.description, p.note)
+ def apply(l: Iterable[Project]) = build(Project, l)
+}
+
+
+
+// vim: set ts=2 sw=2 et:
--- a/src/main/webapp/company/view.html Fri Apr 27 16:18:28 2012 +0200
+++ b/src/main/webapp/company/view.html Tue May 01 21:40:36 2012 +0200
@@ -17,6 +17,12 @@
<span class="lift:contacts"></span>
</div>
</div> <!-- /row -->
+ <div class="row section">
+ <div class="span12">
+ <h3><span class="lift:loc?locid=Projects"></span></h3>
+ <span class="lift:projects"></span>
+ </div>
+ </div> <!-- /row -->
</div>
</body>
</html>
--- a/src/main/webapp/templates-hidden/_resources.html Fri Apr 27 16:18:28 2012 +0200
+++ b/src/main/webapp/templates-hidden/_resources.html Tue May 01 21:40:36 2012 +0200
@@ -190,6 +190,7 @@
Really delete this project?
Project %s deleted.
-->
+ <res name="Projects" lang="en" default="true">Projects</res>
<!-- project fields -->
<res name="project.name" lang="en" default="true">Name</res>
<res name="project.note" lang="en" default="true">Note</res>
@@ -200,6 +201,7 @@
<res name="project.responsible" lang="en" default="true">Responsible</res>
<res name="project.stateFld" lang="en" default="true">State</res>
<res name="project.tasks" lang="en" default="true">Tasks</res>
+ <res name="project.company" lang="en" default="true">Company</res>
<!-- project states -->
<res name="project.state.assigned" lang="en" default="true">Assigned</res>
<res name="project.state.paused" lang="en" default="true">Paused</res>
--- a/src/main/webapp/templates-hidden/_resources_cs.html Fri Apr 27 16:18:28 2012 +0200
+++ b/src/main/webapp/templates-hidden/_resources_cs.html Tue May 01 21:40:36 2012 +0200
@@ -190,6 +190,7 @@
<res name="project.responsible" lang="cs">Odpovědný</res>
<res name="project.stateFld" lang="cs">Stav</res>
<res name="project.tasks" lang="cs">Úkoly</res>
+ <res name="project.company" lang="cs">Společnost</res>
<!-- project states -->
<res name="project.state.assigned" lang="cs">Přidělen</res>
<res name="project.state.paused" lang="cs">Pozastaven</res>